/*
	状态量说明:

	inspect_status - 独立资源
		1	： 		占用状态
		-1	：		关闭状态

	data_binding_preview_status - 独立资源
		1	:		占用状态
		-1	:		关闭状态
	
	data_set_preview_status - 独立资源
		1	:		占用状态
		-1	:		关闭状态

	current_action - 当前是谁在占用inspector
		INSPECTOR_CURRENT_FREE						101:	没人占用
		INSPECTOR_CURRENT_DATA_BINDING_XPATH		102:	data binding 的数据结构
		INSPECTOR_CURRENT_DATA_BINDING_MAX_XPATH	103:	data binding 的最大范围
		INSPECTOR_CURRENT_TARGET_DATA				104:	data set 的目标数据
		INSPECTOR_CURRENT_CONTINUES					105:	continues获取目标数据
		
*/

const INSPECTOR_STATUS_ON = 1;
const INSPECTOR_STATUS_OFF = -1;
const INSPECTOR_CURRENT_FREE = 101;
const INSPECTOR_CURRENT_DATA_BINDING_XPATH = 102;
const INSPECTOR_CURRENT_DATA_BINDING_MAX_XPATH = 103;
const INSPECTOR_CURRENT_TARGET_DATA = 104;
const INSPECTOR_CURRENT_CONTINUES = 105;

var inspect_status = INSPECTOR_STATUS_OFF;
var data_binding_preview_status = -1;
var current_action = INSPECTOR_CURRENT_FREE;

const XPATH_TYPE_SIMPLIST_TURN_PAGE_BUTTON = 120;           // 获取翻页按钮的xpath
const XPATH_TYPE_SIMPLIST_GET_DATA_BINDING = 121;
const XPATH_TYPE_SIMPLIST_WATERFALL_BUTTON = 122;

const XPATH_TYPE_STRUCTURE_GET_DATA_BINDING = 125;
const XPATH_TYPE_CONTINUES_GET_DATA = 130;



const MSG_NORMAL = 0;                           // background.js 不必改动发送的消息, 可以直接发送给content.js
const MSG_SPEFIFIC = 1;                         // background.js 需要重新包装消息
/*
=========================
数据结构
=========================
*/
class Queue{
	constructor(){
		/*
			list:			[][][][] 头 -> 尾
			list element: 	jQuery
		*/
		this.queue = null;
		this.length = null;
	}

	// 初始化队列
	init_queue(){
		this.queue = new Array();
		this.length = 0;
	}

	// 清理队列
	clear_queue(){
		this.queue = new Array();
		this.length = 0;
	}

	// 销毁队列
	destory_queue(){
		this.queue = null;
		this.length = null;
	}

	// 进队列
	push(element){
		if (this.queue === null){
			// 队列没有初始化
			return false;
		}

		this.queue.push(element);
		this.length++;
	}

	// 出队列, 返回出队列的元素
	pop(){
		if (this.queue === null){
			// 队列没有初始化
			return false;
		}
		this.length--;
		return this.queue.shift();
	}

	// 转换为array对象(元素类型为str， 值表示xpath)
	to_str_xpath_array(){
		if (this.queue === null){
			// 队列没有初始哈u
			return false;
		}

		let list_xpath = new Array();

		for (let i = 0; i < this.length; i++) {
			let element = utility.jq2xpath(this.queue[i]);
			list_xpath.push(element);
		}

		return list_xpath;
	}


}

class XpathNode{
	/*
		xpath节点对象
	*/
	constructor(){
		this.tag_name = null;			// 小写标签名
		this.has_same_brother = false;  // 是否有同名兄弟标签 div[3]: div
		this.index = null;				// 是第几个同名标签(int) div[3]: 3
	}

	xath_node_obj_to_string(){
		/*
			输出该节点的xpath字符串 形如 "div[1]" "html"
			不带斜杠
		*/
		if (this.tag_name === null){
			return false
		}

		let str_xpath = "";
		if (this.has_same_brother === true){
			str_xpath = this.tag_name + "[" + this.index + "]";
		}else if (this.has_same_brother === false){
			str_xpath = this.tag_name;
		}else{
			return false;
		}

		return str_xpath;
	}

	string_to_xath_node_obj(str_xpath){
		/*
			将字符串xpath转化为本对象 形如 div[4]
			字符串xpath不带斜杆
		*/

		if (str_xpath === "" || str_xpath === undefined){
			return false;
		}

		if (str_xpath.slice(0,1) === "/" || str_xpath.slice(-1) === "/"){
			return false;
		}

		// 带下标
		if (str_xpath.slice(-1) === "]"){
			let str_list = str_xpath.split("[");
			this.tag_name = str_list[0];
			this.index = Number(str_list[1].split("]")[0]);
			this.has_same_brother = true;
		}else{
			this.tag_name = str_xpath;
			this.has_same_brother = false;
		}
	}

	jquery_to_xpath_node_obj(jq_obj){
		/*
			jQuery 转换为 xpath node对象
		*/
		if (jq_obj === null || jq_obj === undefined){
			console.log("jquery_to_xpath_node_obj: error - jq_obj is null");
			return false;
		}
		let jq_path = utility.jq2xpath(jq_obj);

		let list = jq_path.split("/");
		this.string_to_xath_node_obj(list[list.length-1]);		
		return true;
	}
}


class CrossList{
	constructor(){
		this.node_space = new Array();
		this.list_space = new Array();
		this.root = null;
	}

	init_list(){
		this.node_space = new Array();
		this.list_space = new Array();
		this.root = null;
	}

	add_node_element(data){
		this.node_space.push(data);
	}

	// 生成的是jq list
	generate_list_space(){
		if (this.root === null){
			console.log("CrossList.generate_list_space");
			console.log("Error: root is not define");
			return false;
		}

		let queue = new Queue();
		queue.init_queue();
		queue.push(this.root);

		while(queue.length != 0){
			let list_space_element = new Object();
			let jq_element = queue.pop();
			list_space_element.jq_obj = jq_element;

			// down
			if (jq_element.children().length === 0){
				list_space_element.left = null;
			}else{
				list_space_element.left = $(jq_element.children()[0]);
				for (let i = 0; i < jq_element.children().length; i++) {
					queue.push($(jq_element.children()[i]));
				}
			}

			
			// right
			if (jq_element.next().length != 0){
				list_space_element.right = jq_element.next();
			}else{
				list_space_element.right = null;
			}
			
			this.list_space.push(list_space_element);
			this.list_space
		}
		console.log(this.list_space);
	}

	// 生成jq 的节点list
	generate_node_space(){
		for (let j = 0; j < this.list_space.length; j++) {
			const element = this.list_space[j];
			this.node_space.push(element.jq_obj);
		}
	}

	// 转换两个list
	transform_list(){
		let new_list = new Array();
		for (let i = 0; i < this.list_space.length; i++) {
			const element = this.list_space[i];
			let element_index = -1;
			let element_left_index = -1;
			let element_right_index = -1;
			element_index = this.get_jqObj_index(element.jq_obj);
			if (element.left !== null && element.left !== undefined){
				element_left_index = this.get_jqObj_index(element.left);
			}
			if (element.right !== null && element.right !== undefined){
				element_right_index = this.get_jqObj_index(element.right);
			}

			let new_element = new Object();
			new_element.left = element_left_index;
			new_element.node_value = element_index;
			new_element.right = element_right_index;

			new_list.push(new_element);
		}

		let new_node_list = new Array();
		for (let j = 0; j < this.node_space.length; j++) {
			let element = this.node_space[j];
			let new_element = new Object();
			
			let attr_length = 0
			for (let k = 0; k < element[0].attributes.length; k++) {
				let attr = element[0].attributes[k];
				let new_attr = new Object();
				new_attr.name = attr.name;
				new_attr.value = attr.value;
				new_element["attr_" + k] = new_attr;
				attr_length++;
			}

			new_element.tag_name = element[0].tagName;
			new_element.attr_length = attr_length;
			if (element[0].childNodes.length > 0 && (element[0].childNodes[0] instanceof Text)){
				new_element.text = element[0].childNodes[0].textContent;
			}else{
				new_element.text = '';
			}
			new_node_list.push(new_element);
		}

		this.list_space = new_list;
		this.node_space = new_node_list;
	}

	get_jqObj_index(jq_obj){
		/*
			返回jq_obj在node_space中的下标
			如果找不到，或者输入数据不合法，返回-1;
		*/
		if (jq_obj instanceof jQuery === false){
			console.log("==get_jqObj_index==");
			console.log("Error");
			console.log("jq_obj is not a jQuery object");
			return -1;
		}

		let count = 0;
		for (let i = 0; i < this.node_space.length; i++) {
			const element = this.node_space[i];
			if (element.is(jq_obj)){
				return count;
			}else{
				count++;
			}
		}

		// 找不到
		if (count >= this.node_space.length){
			return -1;
		}
	}

}


class Inspector {

    /*
    ==========
    get value
    ==========
    */

    constructor() {
      this.win = window;
      this.doc = window.document;

      this.draw = this.draw.bind(this);
      this.getData = this.getData.bind(this);
      this.setOptions = this.setOptions.bind(this);

      this.cssNode = 'xpath-css';
      this.contentNode = 'xpath-content';
	  this.overlayElement = 'xpath-overlay';
	  

	  this.is_lock_max = -1;
	  this.lock_max = null;

	  // 临时变量 - 当前请求的消息体
	  this.current_msg = null;
	}

	// 初始化消息体
	init_current_msg(){
		this.current_msg = null;
	}
	
	// 初始化锁定变量
	init_lock_max(){
		this.is_lock_max = -1;
		this.lock_max = null;
	}

    getData(e) {
		e.stopImmediatePropagation();               // 停止其他监听器
		e.preventDefault && e.preventDefault();     // 取消该元素事件的默认行为（如，a不会跳转）
		e.stopPropagation && e.stopPropagation();   // 阻止事件冒泡

		if (e.target.id !== this.contentNode) {
			const XPath = this.getXPath(e.target);    // 获取元素的Xpath
			this.XPath = XPath;
			const contentNode = document.getElementById(this.contentNode);    // 设置元素的内容为xpath
			if (contentNode) {
				contentNode.innerText = XPath;
			} else {
				const contentHtml = document.createElement('div');
				contentHtml.innerText = XPath;
				contentHtml.id = this.contentNode;
				document.body.appendChild(contentHtml);
			}
			this.options.clipboard && ( this.copyText(XPath) );
			
			if(current_action == INSPECTOR_CURRENT_DATA_BINDING_XPATH){
				let return_obj = new Object();
				return_obj.todo = "data_binding_xpath";
				return_obj.msg_type = MSG_NORMAL;
				return_obj.todo_type = this.current_msg.todo_type;

				if (this.current_msg.todo_type === XPATH_TYPE_SIMPLIST_TURN_PAGE_BUTTON){
					let full_xpath = utility.id_xpath_to_full_xpath(XPath);
					return_obj.xpath = full_xpath;
					return_obj.scrollTop = utility.get_ScrollTop();
					

				}else if(this.current_msg.todo_type === XPATH_TYPE_SIMPLIST_WATERFALL_BUTTON){
					let full_xpath = utility.id_xpath_to_full_xpath(XPath);
					return_obj.xpath = full_xpath;
					return_obj.scrollTop = utility.get_ScrollTop();
				}else if(this.current_msg.todo_type === XPATH_TYPE_STRUCTURE_GET_DATA_BINDING){
					// 将xpath装换为全路径
					let full_xpath = utility.id_xpath_to_full_xpath(XPath);

					let max_path = null

					if (this.is_lock_max === -1){
						// 生成xpath的最大范围(父节点)
						let max_data_binding_xpath = utility.get_xpath_patern(XPath);
						max_path = max_data_binding_xpath;
					}else{
						max_path = this.lock_max;
					}

					// 检测xpath 是否在 max_path里面
					if (utility.is_xpath_in_max_path(XPath, max_path) === true){
						let result_obj = utility.autoSubRange(XPath, max_path);

						// 缓存数据
						inspect_with_border.current_data_binding_xpath = full_xpath;
						inspect_with_border.current_data_binding_max = max_path;

						return_obj.is_success = 1;
						return_obj.xpath = full_xpath;
						return_obj.max_data_binding_xpath = max_path;
						return_obj.list_sub_range_xpath = result_obj.list_sub_range_xpath;
					}else{
						return_obj.is_success = -1;
					}

					// 生成十字链表
					let cross_list = new CrossList();
					cross_list.root = utility.xpath2jq(full_xpath);
					cross_list.generate_list_space();
					cross_list.generate_node_space();
					cross_list.transform_list();
					console.log("List Space:");
					console.log(cross_list.list_space);

					console.log("Node Space:");
					console.log(cross_list.node_space);
					// cross_list
					return_obj.cross_list_space = cross_list.list_space;
					return_obj.cross_node_space = cross_list.node_space;

				}else{
					
					// 将xpath装换为全路径
					let full_xpath = utility.id_xpath_to_full_xpath(XPath);

					let max_path = null

					if (this.is_lock_max === -1){
						// 生成xpath的最大范围(父节点)
						let max_data_binding_xpath = utility.get_xpath_patern(XPath);
						max_path = max_data_binding_xpath;
					}else{
						max_path = this.lock_max;
					}

					// 检测xpath 是否在 max_path里面
					if (utility.is_xpath_in_max_path(XPath, max_path) === true){
						let result_obj = utility.autoSubRange(XPath, max_path);

						// 缓存数据
						inspect_with_border.current_data_binding_xpath = full_xpath;
						inspect_with_border.current_data_binding_max = max_path;

						return_obj.is_success = 1;
						return_obj.xpath = full_xpath;
						return_obj.max_data_binding_xpath = max_path;
						return_obj.list_sub_range_xpath = result_obj.list_sub_range_xpath;
					}else{
						return_obj.is_success = -1;
					}
				}

				// 将xpath发送给background
				console.log("send xpath to background");
				chrome.runtime.sendMessage(return_obj, function(response) {
					console.log("send success and get response");
				});		
				
			}else if(current_action == INSPECTOR_CURRENT_DATA_BINDING_MAX_XPATH){
				console.log("send max range to background");
				
				// 将xpath装换为全路径
				let full_xpath = utility.id_xpath_to_full_xpath(XPath);

				// 检查最大范围是否有效
				let is_success = false;
				if (inspect_with_border.current_data_binding_xpath === null){
					inspect_with_border.current_data_binding_max = full_xpath;
					is_success = true;
				}else{
					let jq_tmp_current_xpath = utility.xpath2jq(inspect_with_border.current_data_binding_xpath);
					let jq_tmp_max = utility.xpath2jq(full_xpath);
					while(1){
						if (jq_tmp_current_xpath.parent().is(jq_tmp_max)){
							// 找到了,说明最大范围有效
							is_success = true;
							break;
						}

						jq_tmp_current_xpath = jq_tmp_current_xpath.parent();
						if (jq_tmp_current_xpath[0].tagName.toLowerCase() === "body"){
							// 到头了, 没有找到说明无效
							is_success = false;
							break;
						}
					}
				}

				chrome.runtime.sendMessage({
					todo: "maxRangeXpath",
					xpath: full_xpath,
					is_success: is_success,
					msg_type: MSG_NORMAL
				}, function(response) {
					console.log("send success and get response");
				});
			}else if(current_action == INSPECTOR_CURRENT_TARGET_DATA){
				// 获取数据组数据
				let return_obj = new Object();
				return_obj.todo = "data_set_target_value";
				return_obj.msg_type = MSG_NORMAL;

				// 校验获取的xpath是否合法
				let data_binding_xpath = null;
				if (this.current_msg.xpath){
					data_binding_xpath = this.current_msg.xpath;
				}else{
					console.log("=GET XPATH ERROR=");
					console.log("inspect.current_msg:");
					console.log(inspect.current_msg);
					return_obj.is_success = -1;
					chrome.runtime.sendMessage(return_obj);
					return false;
				}

				let full_xpath = utility.id_xpath_to_full_xpath(XPath);

				// let jq_data_binding_xpath = utility.xpath2jq(data_binding_xpath);
				// let jq_target_data_xpath = utility.xpath2jq(full_xpath);

				if (utility.is_xpath_in_max_path(full_xpath, data_binding_xpath) === true){
					// 验证成功
					return_obj.is_success = 1;
					return_obj.xpath = full_xpath;
					return_obj.scroll_top = utility.get_ScrollTop();

					// 发送消息
					chrome.runtime.sendMessage(return_obj);

				}else{
					// 验证失败
					return_obj.is_success = -1;

					// 发送消息
					chrome.runtime.sendMessage(return_obj);

				}

			}else if(current_action == INSPECTOR_CURRENT_CONTINUES){
				let return_obj = new Object();
				let full_xpath = utility.id_xpath_to_full_xpath(XPath);
				return_obj.todo = "getDataContinues";
				return_obj.msg_type = MSG_NORMAL;
				return_obj.xpath = full_xpath;
				return_obj.is_success = true;
				chrome.runtime.sendMessage(return_obj);
			}	
		}
    }

    // 初始化
    getOptions() {
      const storage = chrome.storage && (chrome.storage.local);
      const promise = storage.get({  // 赋予默认值
        inspector: true,
        clipboard: true,
        shortid: true,
        position: 'bl'
      }, this.setOptions);
      (promise && promise.then) && (promise.then(this.setOptions()));
    }

    setOptions(options) {
      this.options = options;
      let position = 'bottom:0;left:0';
      switch (options.position) {
        case 'tl': position = 'top:0;left:0'; break;
        case 'tr': position = 'top:0;right:0'; break;
        case 'br': position = 'bottom:0;right:0'; break;
        default: break;
      }
      this.styles = `*{cursor:crosshair!important;}#xpath-content{${position};cursor:initial!important;padding:10px;background:gray;color:white;position:fixed;font-size:14px;z-index:10000001;}`;
      this.activate();
    }

    createOverlayElements() {
      const overlayStyles = {
        background: 'rgba(120, 170, 210, 0.7)',
        padding: 'rgba(77, 200, 0, 0.3)',
        margin: 'rgba(255, 155, 0, 0.3)',
        border: 'rgba(255, 200, 50, 0.3)'
      };

      this.container = this.doc.createElement('div');
      this.node = this.doc.createElement('div');
      this.border = this.doc.createElement('div');
      this.padding = this.doc.createElement('div');
      this.content = this.doc.createElement('div');

      this.border.style.borderColor = overlayStyles.border;
      this.padding.style.borderColor = overlayStyles.padding;
      this.content.style.backgroundColor = overlayStyles.background;

      Object.assign(this.node.style, {
        borderColor: overlayStyles.margin,
        pointerEvents: 'none',
        position: 'fixed'
      });

      this.container.id = this.overlayElement;
      this.container.style.zIndex = 10000000;
      this.node.style.zIndex = 10000000;

      this.container.appendChild(this.node);
      this.node.appendChild(this.border);
      this.border.appendChild(this.padding);
      this.padding.appendChild(this.content);
    }

    removeOverlay() {
      const overlayHtml = document.getElementById(this.overlayElement);
      overlayHtml && overlayHtml.remove();
    }

    copyText(XPath) {
      const hdInp = document.createElement('textarea');
      hdInp.textContent = XPath;
      document.body.appendChild(hdInp);
      hdInp.select();
      document.execCommand('copy');
      hdInp.remove();
    }

    draw(e) {
      const node = e.target;
      if (node.id !== this.contentNode) {
        this.removeOverlay();

        const box = this.getNestedBoundingClientRect(node, this.win);
        const dimensions = this.getElementDimensions(node);

        this.boxWrap(dimensions, 'margin', this.node);
        this.boxWrap(dimensions, 'border', this.border);
        this.boxWrap(dimensions, 'padding', this.padding);

        Object.assign(this.content.style, {
          height: box.height - dimensions.borderTop - dimensions.borderBottom - dimensions.paddingTop - dimensions.paddingBottom + 'px',
          width: box.width - dimensions.borderLeft - dimensions.borderRight - dimensions.paddingLeft - dimensions.paddingRight + 'px',
        });

        Object.assign(this.node.style, {
          top: box.top - dimensions.marginTop + 'px',
          left: box.left - dimensions.marginLeft + 'px',
        });

        this.doc.body.appendChild(this.container);
      }
    }

    activate() {
      this.createOverlayElements();
      // add styles
      if (!document.getElementById(this.cssNode)) {
        const styles = document.createElement('style');
        styles.innerText = this.styles;
        styles.id = this.cssNode;
        document.getElementsByTagName('head')[0].appendChild(styles);
      }
      // add listeners
      // use capture = true，阻止了其他元素的click事件
      document.addEventListener('click', this.getData, true);
      this.options.inspector && ( document.addEventListener('mouseover', this.draw) );  // 前一个条件的意义?
    }

    deactivate() {
      // remove styles
      const cssNode = document.getElementById(this.cssNode);
      cssNode && cssNode.remove();
      // remove overlay
      this.removeOverlay();
      // remove xpath html
      const contentNode = document.getElementById(this.contentNode);
      contentNode && contentNode.remove();
      // remove listeners
      document.removeEventListener('click', this.getData, true);
      this.options && this.options.inspector && ( document.removeEventListener('mouseover', this.draw) );
    }

    // el 是event的target对象(element)
    getXPath(el) {
      let nodeElem = el;
      if (nodeElem.id && this.options.shortid) {
        return `//*[@id="${nodeElem.id}"]`;
      }
      const parts = [];
      while (nodeElem && nodeElem.nodeType === Node.ELEMENT_NODE) { // https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType
        let nbOfPreviousSiblings = 0;
        let hasNextSiblings = false;
        let sibling = nodeElem.previousSibling;
        while (sibling) {
          if (sibling.nodeType !== Node.DOCUMENT_TYPE_NODE && sibling.nodeName === nodeElem.nodeName) {
            nbOfPreviousSiblings++;
          }
          sibling = sibling.previousSibling;
        }
        sibling = nodeElem.nextSibling;
        while (sibling) {
          if (sibling.nodeName === nodeElem.nodeName) {
            hasNextSiblings = true;
            break;
          }
          sibling = sibling.nextSibling;
        }
        const prefix = nodeElem.prefix ? nodeElem.prefix + ':' : '';
        const nth = nbOfPreviousSiblings || hasNextSiblings ? `[${nbOfPreviousSiblings + 1}]` : '';
        parts.push(prefix + nodeElem.localName + nth);
        nodeElem = nodeElem.parentNode;
      }
      return parts.length ? '/' + parts.reverse().join('/') : '';
    }

    getElementDimensions(domElement) {
      const calculatedStyle = window.getComputedStyle(domElement);
      return {
        borderLeft: +calculatedStyle.borderLeftWidth.match(/[0-9]*/)[0],
        borderRight: +calculatedStyle.borderRightWidth.match(/[0-9]*/)[0],
        borderTop: +calculatedStyle.borderTopWidth.match(/[0-9]*/)[0],
        borderBottom: +calculatedStyle.borderBottomWidth.match(/[0-9]*/)[0],
        marginLeft: +calculatedStyle.marginLeft.match(/[0-9]*/)[0],
        marginRight: +calculatedStyle.marginRight.match(/[0-9]*/)[0],
        marginTop: +calculatedStyle.marginTop.match(/[0-9]*/)[0],
        marginBottom: +calculatedStyle.marginBottom.match(/[0-9]*/)[0],
        paddingLeft: +calculatedStyle.paddingLeft.match(/[0-9]*/)[0],
        paddingRight: +calculatedStyle.paddingRight.match(/[0-9]*/)[0],
        paddingTop: +calculatedStyle.paddingTop.match(/[0-9]*/)[0],
        paddingBottom: +calculatedStyle.paddingBottom.match(/[0-9]*/)[0]
      };
    }

    getOwnerWindow(node) {
      if (!node.ownerDocument) { return null; }
      return node.ownerDocument.defaultView;
    }

    getOwnerIframe(node) {
      const nodeWindow = this.getOwnerWindow(node);
      if (nodeWindow) {
        return nodeWindow.frameElement;
      }
      return null;
    }

    getBoundingClientRectWithBorderOffset(node) {
      const dimensions = this.getElementDimensions(node);
      return this.mergeRectOffsets([
        node.getBoundingClientRect(),
        {
          top: dimensions.borderTop,
          left: dimensions.borderLeft,
          bottom: dimensions.borderBottom,
          right: dimensions.borderRight,
          width: 0,
          height: 0
        }
      ]);
    }

    mergeRectOffsets(rects) {
      return rects.reduce((previousRect, rect) => {
        if (previousRect === null) { return rect; }
        return {
          top: previousRect.top + rect.top,
          left: previousRect.left + rect.left,
          width: previousRect.width,
          height: previousRect.height,
          bottom: previousRect.bottom + rect.bottom,
          right: previousRect.right + rect.right
        };
      });
    }

    getNestedBoundingClientRect(node, boundaryWindow) {
      const ownerIframe = this.getOwnerIframe(node);
      if (ownerIframe && ownerIframe !== boundaryWindow) {
        const rects = [node.getBoundingClientRect()];
        let currentIframe = ownerIframe;
        let onlyOneMore = false;
        while (currentIframe) {
          const rect = this.getBoundingClientRectWithBorderOffset(currentIframe);
          rects.push(rect);
          currentIframe = this.getOwnerIframe(currentIframe);
          if (onlyOneMore) { break; }
          if (currentIframe && this.getOwnerWindow(currentIframe) === boundaryWindow) {
            onlyOneMore = true;
          }
        }
        return this.mergeRectOffsets(rects);
      }
      return node.getBoundingClientRect();
    }

    boxWrap(dimensions, parameter, node) {
      Object.assign(node.style, {
        borderTopWidth: dimensions[parameter + 'Top'] + 'px',
        borderLeftWidth: dimensions[parameter + 'Left'] + 'px',
        borderRightWidth: dimensions[parameter + 'Right'] + 'px',
        borderBottomWidth: dimensions[parameter + 'Bottom'] + 'px',
        borderStyle: 'solid'
      });
    }
}

class Preview{

    constructor(){
        this.xpath = "";
        this.win = window;
        this.doc = window.document;

        this.draw = this.draw.bind(this);

        this.cssNode = 'xpath-css';
        this.contentNode = 'xpath-content';
        this.overlayElement = 'xpath-overlay';
    }

    createOverlayElements() {
        const overlayStyles = {
            background: 'rgba(120, 170, 210, 0.7)',
            padding: 'rgba(77, 200, 0, 0.3)',
            margin: 'rgba(255, 155, 0, 0.3)',
            border: 'rgba(255, 200, 50, 0.3)'
        };

        this.container = this.doc.createElement('div');
        this.node = this.doc.createElement('div');
        this.border = this.doc.createElement('div');
        this.padding = this.doc.createElement('div');
        this.content = this.doc.createElement('div');

        this.border.style.borderColor = overlayStyles.border;
        this.padding.style.borderColor = overlayStyles.padding;
        this.content.style.backgroundColor = overlayStyles.background;

        Object.assign(this.node.style, {
            borderColor: overlayStyles.margin,
            pointerEvents: 'none',
            position: 'fixed'
        });

        this.container.id = this.overlayElement;
        this.container.style.zIndex = 10000000;
        this.node.style.zIndex = 10000000;

        this.container.appendChild(this.node);
        this.node.appendChild(this.border);
        this.border.appendChild(this.padding);
        this.padding.appendChild(this.content);
    }

    removeOverlay() {
        const overlayHtml = document.getElementById(this.overlayElement);
    overlayHtml && overlayHtml.remove();
    }

    getElementDimensions(domElement) {
        const calculatedStyle = window.getComputedStyle(domElement);
        return {
            borderLeft: +calculatedStyle.borderLeftWidth.match(/[0-9]*/)[0],
            borderRight: +calculatedStyle.borderRightWidth.match(/[0-9]*/)[0],
            borderTop: +calculatedStyle.borderTopWidth.match(/[0-9]*/)[0],
            borderBottom: +calculatedStyle.borderBottomWidth.match(/[0-9]*/)[0],
            marginLeft: +calculatedStyle.marginLeft.match(/[0-9]*/)[0],
            marginRight: +calculatedStyle.marginRight.match(/[0-9]*/)[0],
            marginTop: +calculatedStyle.marginTop.match(/[0-9]*/)[0],
            marginBottom: +calculatedStyle.marginBottom.match(/[0-9]*/)[0],
            paddingLeft: +calculatedStyle.paddingLeft.match(/[0-9]*/)[0],
            paddingRight: +calculatedStyle.paddingRight.match(/[0-9]*/)[0],
            paddingTop: +calculatedStyle.paddingTop.match(/[0-9]*/)[0],
            paddingBottom: +calculatedStyle.paddingBottom.match(/[0-9]*/)[0]
        };
    }

    getOwnerWindow(node) {
        if (!node.ownerDocument) { return null; }
        return node.ownerDocument.defaultView;
    }

    getOwnerIframe(node) {
        const nodeWindow = this.getOwnerWindow(node);
        if (nodeWindow) {
            return nodeWindow.frameElement;
        }
        return null;
    }

    getBoundingClientRectWithBorderOffset(node) {
        const dimensions = this.getElementDimensions(node);
        return this.mergeRectOffsets([
            node.getBoundingClientRect(),
            {
            top: dimensions.borderTop,
            left: dimensions.borderLeft,
            bottom: dimensions.borderBottom,
            right: dimensions.borderRight,
            width: 0,
            height: 0
            }
        ]);
    }

    mergeRectOffsets(rects) {
        return rects.reduce((previousRect, rect) => {
            if (previousRect === null) { return rect; }
            return {
            top: previousRect.top + rect.top,
            left: previousRect.left + rect.left,
            width: previousRect.width,
            height: previousRect.height,
            bottom: previousRect.bottom + rect.bottom,
            right: previousRect.right + rect.right
            };
        });
    }

    getNestedBoundingClientRect(node, boundaryWindow) {
        const ownerIframe = this.getOwnerIframe(node);
        if (ownerIframe && ownerIframe !== boundaryWindow) {
            const rects = [node.getBoundingClientRect()];
            let currentIframe = ownerIframe;
            let onlyOneMore = false;
            while (currentIframe) {
            const rect = this.getBoundingClientRectWithBorderOffset(currentIframe);
            rects.push(rect);
            currentIframe = this.getOwnerIframe(currentIframe);
            if (onlyOneMore) { break; }
            if (currentIframe && this.getOwnerWindow(currentIframe) === boundaryWindow) {
                onlyOneMore = true;
            }
            }
            return this.mergeRectOffsets(rects);
        }
        return node.getBoundingClientRect();
    }

    boxWrap(dimensions, parameter, node) {
        Object.assign(node.style, {
            borderTopWidth: dimensions[parameter + 'Top'] + 'px',
            borderLeftWidth: dimensions[parameter + 'Left'] + 'px',
            borderRightWidth: dimensions[parameter + 'Right'] + 'px',
            borderBottomWidth: dimensions[parameter + 'Bottom'] + 'px',
            borderStyle: 'solid'
        });
    }

    draw(el) {
        const node = el;
        if (node.id !== this.contentNode) {
            this.removeOverlay();

            const box = this.getNestedBoundingClientRect(node, this.win);
            const dimensions = this.getElementDimensions(node);

            this.boxWrap(dimensions, 'margin', this.node);
            this.boxWrap(dimensions, 'border', this.border);
            this.boxWrap(dimensions, 'padding', this.padding);

            Object.assign(this.content.style, {
                height: box.height - dimensions.borderTop - dimensions.borderBottom - dimensions.paddingTop - dimensions.paddingBottom + 'px',
                width: box.width - dimensions.borderLeft - dimensions.borderRight - dimensions.paddingLeft - dimensions.paddingRight + 'px',
            });

            Object.assign(this.node.style, {
                top: box.top - dimensions.marginTop + 'px',
                left: box.left - dimensions.marginLeft + 'px',
            });

            this.doc.body.appendChild(this.container);
        }
    }

    // 转换
    exchange(s_xpath){
        console.log("exchange xpath to element");
        if(s_xpath.startsWith("//*")){
            let length = s_xpath.length;
            let target_id = s_xpath.substring(9, length-2);
            console.log("target id = " + target_id);
            let element = document.getElementById(target_id);
            return element;
        }else{

        }
    }

    // 设置xpath
    setXpath(s_value){
        this.xpath = s_value;
    }

    // 激活状态，显示元素
    activate(s_input){
        console.log("==content=activate");

        // 创建遮罩
        this.createOverlayElements();

        // 取消其他事件监听、事件冒泡等
        // e.stopImmediatePropagation();               // 停止其他监听器
        // e.preventDefault && e.preventDefault();     // 取消该元素事件的默认行为（如，a不会跳转）
        // e.stopPropagation && e.stopPropagation();   // 阻止事件冒泡

        // 将xpath转换为element
        this.setXpath(s_input);

        let element = this.exchange(this.xpath);

        this.draw(element);
    }

    // 取消激活状态
    deactivate(){
        // remove styles
        const cssNode = document.getElementById(this.cssNode);
        cssNode && cssNode.remove();
        // remove overlay
        this.removeOverlay();
        // remove xpath html
        const contentNode = document.getElementById(this.contentNode);
        contentNode && contentNode.remove();
    }
}

class Utility{
	/*
	==========================
	工具类
	实现xpath, jQuery对象的所有转换
	以及一些和xpath相关的求解算法
	==========================
	*/

	constructor() {
	}

	// xpath to jquery obj
	// 生成的xpath有两种类型: 使用id(形如 - //*[@id="s"]), 使用全路径(形如 - /html/body/div[3]/div/div[2]/div/div[3]/div/ul/li[1])
	// 返回jquery对象
	xpath2jq(xpath){
		// console.log("==xpath2jq start==");
		// 判断xpath类型
		if(xpath.startsWith("//")){
			// console.log("xpath2jq: 生成id的xpath")
			// 使用id
			let str_id = xpath.slice(9, -2);
			let target = $("#" + str_id);
			return target;
		}else if(xpath.startsWith("/")){
			// console.log("xpath2jq: 生成全路径xpath");
			// 使用全路径
			let arr_tag_list = xpath.split("/");

			// 删除第一个空元素
			arr_tag_list.shift();

			// 当前的父节点 - jq_obj
			let el_current_parent = null;
			for (let index = 0; index < arr_tag_list.length; index++) {
				let element = arr_tag_list[index];

				// 标签的名称
				let tag_name = null;
				// 第几个标签(如果有)
				let tag_index = null;

				// 判断元素类型,有两种, 带下标(形如 - div[3]), 不带下标(形如 - html)
				if (element.substr(-1, 1) === "]"){
					// 带下标
					tag_name = element.split("[")[0];
					tag_index = Number(element.split("[")[1].split("]")[0]);
				}else{
					// 不带下标
					tag_name = element;
				}

				if (el_current_parent === null){
					// 初始化
					el_current_parent = $(tag_name);
				}else{
					// console.log("content: xpath2jq - el_current_parent:" + el_current_parent[0].tagName);
					// 获取当前父节点的所有直接子节点
					let arr_all_children = el_current_parent.children();

					// 判断元素类型
					if (tag_index === null){
						// 不带下标
						// 遍历当前父节点的所有直接字节点,查看是否有匹配的节点
						let has_found = -1;
						for (let i = 0; i < arr_all_children.length; i++) {
							if ((arr_all_children[i].tagName).toUpperCase() === tag_name.toUpperCase()){
								// 匹配成功
								// el_current_parent = $(tag_name);
								// arr_all_children[i]是一个Dom对象
								// console.log("xpath2jq: 不带下标的元素 - 匹配成功");
								el_current_parent = $(arr_all_children[i]);
								has_found = 1;
								break;
							}
						}

						// 匹配失败
						if (has_found === -1){
							console.log("xpath2jq: 匹配失败 - 不带下标的元素");
							console.log("xpath2jq: 失败信息 - ");
							console.log("xpath2jq: tag name - " + tag_name);
							console.log("xpath2jq: has_found - " + has_found);
							console.log("xpath2jq: arr_all_chilren.length - " + arr_all_children.length);
							return false;
						}
					}else{
						// 带下标
						let counter = 0;
						// 遍历当前父节点的所有直接字节点,查看是否有匹配的节点
						for (let j = 0; j < arr_all_children.length; j++) {
							if ((arr_all_children[j].tagName).toUpperCase() === tag_name.toUpperCase()){
								counter++;
								if (counter === tag_index){
									// 匹配成功
									// console.log("xpath2jq: 带下标的元素 - 匹配成功");
									el_current_parent = $(arr_all_children[j]);
								}
							}
						}
					}
				}
				
			}

			return el_current_parent;
			
		}else{
			console.log("输入xpath错误");
			return false;
		}
	}

	/*
		jquery obj to xpath
		param jq_obj: jquery 对象
		param has_id: 是否生成带id的xpath,如果是否,则生成全路径	
	*/
	jq2xpath(jq_obj, has_id=false){

		let str_xpath = "";

		if (jq_obj === null || jq_obj === undefined){
			return false;
		}else{

			if (has_id === true){
				// 判断元素有没有id
				if (jq_obj.attr("id") == "" || jq_obj.attr("id") == undefined){
					// 生成全路径
					console.log("jq2xpath: has_id == true while element has no id ... create full xpath");
					str_xpath = this.iteration_create_full_xpath(jq_obj, str_xpath);
				}else{
					// 生成id的xpath
					str_xpath = "//*[@id='" + jq_obj.attr("id") + "']";
				}
				return str_xpath;
			}else if(has_id === false){
				str_xpath = this.iteration_create_full_xpath(jq_obj, str_xpath);
				return str_xpath;
			}else{
				console.log("jq2xpath: error - has_id value error");
				console.log("jq2xpath: has_id:" + has_id);
				return false;
			}	
		}
	}

	// 迭代:向上找同名兄弟节点
	// counter 初始值 = 0
	iteration_find_same_brother_upward(jq_obj_ori, jq_obj_iteartion, counter){
		if (jq_obj_iteartion.prev().length != 0){
			if (jq_obj_ori[0].tagName == jq_obj_iteartion.prev()[0].tagName){
				counter++;
			}

			return this.iteration_find_same_brother_upward(jq_obj_ori, jq_obj_iteartion.prev(), counter);
		}else{
			// 到了尽头,返回找到的数量
			return counter;
		}
	}

	// 迭代:向下找同名兄弟节点
	// counter 初始值 = 0
	iteration_find_same_brother_downward(jq_obj_ori, jq_obj_iteartion, counter){
		if (jq_obj_iteartion.next().length != 0){
			if (jq_obj_ori[0].tagName == jq_obj_iteartion.next()[0].tagName){
				counter++;
			}
			return this.iteration_find_same_brother_downward(jq_obj_ori, jq_obj_iteartion.next(), counter);
		}else{
			// 到了尽头,返回找到的数量
			return counter;
		}
	}

	// 迭代: 生成全路径xpath, 返回xpath
	// 先向上遍历, 如果有就返回, 如果没有就向下遍历
	// xpath 初始值 = ""
	iteration_create_full_xpath(jq_obj, str_xpath){
		let counter = 0;
		counter = this.iteration_find_same_brother_upward(jq_obj, jq_obj, counter);
		if (counter ===  0){
			// 向上找不到
			// 向下找
			counter = this.iteration_find_same_brother_downward(jq_obj, jq_obj, counter);
			if (counter === 0){
				// 向下也找不到, 不用添加下标
				str_xpath = "/" + (jq_obj[0].tagName).toLowerCase() + str_xpath;
			}else{
				// 向下找到了, 则当前的jq对象就是第一个同名标签
				str_xpath = "/" + jq_obj[0].tagName.toLowerCase() + "[1]" + str_xpath;
			}
		}else{
			// 向上找到了, 则当前的jq对象就是第counter+1个同名标签
			str_xpath = "/" + jq_obj[0].tagName.toLowerCase() + "[" + (counter+1) + "]" + str_xpath;
		}

		// 完成一次迭代,进行下一个父节点的处理
		if (jq_obj.parent().length != 0 && jq_obj[0].tagName.toLowerCase() !== "html"){
			// 有父节点并且当前节点不是html
			// html的父节点是document
			return this.iteration_create_full_xpath(jq_obj.parent(), str_xpath);
		}else{
			// 没有父节点, 到了尽头
			// 返回生成的xpath
			return str_xpath;
		}
	}

	// 自动生成最小子结构
	/*
		1. 算法描述:
		初始时,将xpath的标签定义为'最小子结构', 将xpath的父节点定义为'当前父节点'
		从xpath向上,逐层遍历父节点(xpath到最大范围的所有父节点),一直到最大范围
		每次遍历,判断'当前父节点'的所有子节点(不包括子孙节点)是否与'最小子结构'的'相同'(最小子结构的判断,见下说明)
		每次遍历结束
			设置当前父节点为最小子结构
			记录与'最小子结构'相同的节点数量,并与'最大相同数量'进行比较
				如果当前遍历结果大于'最大相同数量',则覆盖之并将'当前父节点'设置为'目标父节点'
				并缓存所有'相同'的标签的xpath
			更新路径
			
		所有遍历结束,输出'目标父节点'和所有sub_range的xpath


		2. 判断'最小子结构'是否相同

		策略A:
			- 标签名是否与最小子结构的根节点名相同
			- 标签能否延着路径到达xpath
	*/
	autoSubRange(xpath, max_range_xpath){
		console.log("Utility: auto sub range - start");
		let jq_xpath = null;						// xpath的jq对象
		let jq_max_range = null;					// 最大范围xpath的jq对象
		let i_max_sub_range_num = 0;				// 最大相同的最小子结构数量
		let xpath_target_parent = "";				// 目标父节点
		let list_sub_range_xpath = new Array();		// 子结构的xpath列表
		let list_XpathNode_path = new Array();		// 路径(XpathNode list) 元素的顺序关系:大到小, 形如 "html, body, ... , target"

		jq_xpath = this.xpath2jq(xpath);
		jq_max_range = this.xpath2jq(max_range_xpath);
		console.log("Utility: jq_xpath - " + jq_xpath[0].tagName);
		console.log("Utility: jq_max_range - " + jq_max_range[0].tagName);
		// 初始化 list_XpathNode_path
		let first_xpath_node = new XpathNode();
		first_xpath_node.jquery_to_xpath_node_obj(jq_xpath);
		list_XpathNode_path.push(first_xpath_node);

		let result_obj = this.iteration_auto_sub_range_strategyA(
			jq_xpath,
			jq_max_range,
			i_max_sub_range_num,
			list_XpathNode_path,
			list_sub_range_xpath,
			xpath_target_parent
		);

		return result_obj;
	}

	/*
		迭代: 生成目标xpath的最小子结构xpath list
		策略1

		param jq_xpath: 				最小子结构的节点的query对象
		param jq_max_range_xpath:		最大范围的节点的query对象
		param max_same_num:				最大相同节点数量				初始值: 0
		param list_XpathNode_path:		路径(XpathNode)
		param list_sub_range_xpath:		最终迭代的结果 - 所有符合筛选条件的子结构的xpath
		param str_target_parent_xpath:	最终迭代的结果 - 目标父节点
		return: 						返回两个数据 list_sub_range_xpath str_target_parent_xpath
	*/
	iteration_auto_sub_range_strategyA(
		jq_xpath,
		jq_max_range_xpath,
		max_same_num,
		list_XpathNode_path,
		list_sub_range_xpath,
		str_target_parent_xpath){
		
		// 获取当前最小子结构的父节点
		let jq_current_parent = jq_xpath.parent();

		// 获取当前父节点的所有直接子节点
		let jq_current_childrens = jq_current_parent.children();

		let same_num = 0;											// 本次迭代找到的同名标签数
		let list_tmp_sub_range_xpath = new Array();					// 本次迭代所有同名子结构的xpath

		for (let j = 0; j < jq_current_childrens.length; j++) {
			const element = jq_current_childrens[j];
			let result_obj = this.is_jq_obj_match_path_v2($(element), list_XpathNode_path);
			same_num += result_obj.num;
			for (let k = 0; k < result_obj.num; k++) {
				const element = result_obj[k];
				list_tmp_sub_range_xpath.push(result_obj.list_xpath[k]);
			}
		}

		// 结束本次迭代
		if (same_num > max_same_num){
			max_same_num = same_num;
			let tmp_xpath = this.jq2xpath(jq_current_parent, false);
			if (tmp_xpath !== false){
				str_target_parent_xpath = tmp_xpath;
			}
			list_sub_range_xpath = list_tmp_sub_range_xpath;
		}

		// 更新路径
		let tmp_current_parent_xpath = this.jq2xpath(jq_current_parent, false);
		let list = tmp_current_parent_xpath.split("/");
		let new_xpath_node_obj = new XpathNode();
		new_xpath_node_obj.string_to_xath_node_obj(list[list.length-1]);
		list_XpathNode_path.unshift(new_xpath_node_obj);

		// 判断迭代结果
		// jq_max_range_xpath.parent().is(jq_current_parent) true
		// jq_current_parent === jq_max_range_xpath.parent() false
		if (jq_max_range_xpath.is(jq_current_parent) === true){
			// 迭代结束
			let result_obj = {
				"list_sub_range_xpath": list_sub_range_xpath,
				"str_target_parent_xpath": str_target_parent_xpath
			};

			return result_obj;
		}else{
			return this.iteration_auto_sub_range_strategyA(
				jq_current_parent,
				jq_max_range_xpath,
				max_same_num,
				list_XpathNode_path,
				list_sub_range_xpath,
				str_target_parent_xpath
			);
		}

	}

	/*
		jquery是否匹配给定路径
		param jq_obj: 					jq对象
		param list_XpathNode_path:		路径(XpathNode)
		param return: 					true - 匹配, false - 不匹配

		弃用
		该函数把匹配的路径写死了
	*/
	is_jq_obj_match_path(jq_obj, list_XpathNode_path){
		let current_jq_obj = jq_obj;
		for (let i = 0; i < list_XpathNode_path.length; i++) {
			const element = list_XpathNode_path[i];
			// 获取当前节点的所有直接字节点
			let children_list = current_jq_obj.children().toArray();
			children_list.unshift(current_jq_obj[0]);

			// 不需要判断数量, 只判定路径
			// 要当前标签所有子标签符合同名的,都检查一次
			if (element.has_same_brother === true){
				let counter = 0;
				for (let j = 0; j < children_list.length; j++) {
					if (children_list[j].tagName === element.tag_name.toUpperCase()){
						counter++;
						if (counter === element.index){
							current_jq_obj = $(children_list[j]);
							break;
						}
					}
				}

				// 找不到
				if (counter < element.index){
					return false;
				}

			}else{
				let counter = 0;
				for (let k = 0; k < children_list.length; k++){
					if (children_list[k].tagName === element.tag_name.toUpperCase()){
						current_jq_obj = $(children_list[k]);
						break;
					}
					counter++;
				}

				// 找不到
				if (counter >= children_list.length){
					return false;
				}
			}
		}
		return true;
	}


	/*
		匹配jq对象是否匹配指定路径
		用于iteration_auto_sub_range_strategyA(), 策略函数负责找到当前父节点的字节点里面同名的子结构,
		该函数负责检查找到的子结构是否能沿着路径到达目标xpath, 如果可以,返回匹配的数量以及匹配到的xpath
		param jq_obj: 				目标标签的jq对象(当前父节点的字节点之一)
		param list_XpathNode_path: 	路径(XpathNode)
		return: {
			num:			匹配到的数量
			list_xpath:		匹配到的xpath 	
		}

	*/
	is_jq_obj_match_path_v2(jq_obj, list_XpathNode_path){
		let jq_obj_queue = new Queue();
		let path_queue = new Queue();
		jq_obj_queue.init_queue();
		path_queue.init_queue();

		// jq_obj 进队列，作为起始元素
		jq_obj_queue.push(jq_obj);

		// 让所有路径进队列
		for (let j = 0; j < list_XpathNode_path.length; j++) {
			const path = list_XpathNode_path[j];
			path_queue.push(path);
		}

		// 遍历path queue
		// path queue的节点是否和当前的path obj同名，如果同名，将其所有子节点入队列
		// 一直遍历到最后一个path queue元素
		// 对最后一个path queue元素做同样的操作，最后还留在队列里面的，就是本次遍历最后要找的结果（也是本函数最后输出的结果）
		while(path_queue.length !== null && path_queue.length !== 1){
			// 获取当前的路径
			let current_path_xpath_node = path_queue.pop();
			let children_queue_length = jq_obj_queue.length;

			for (let k = 0; k < children_queue_length; k++) {
				let jq_node = jq_obj_queue.pop();

				if (jq_node[0].tagName.toLowerCase() === current_path_xpath_node.tag_name.toLowerCase()){
					// 同名，将jq_node的所有子节点入队列
					for (let l = 0; l < jq_node.children().length; l++) {
						jq_obj_queue.push($(jq_node.children()[l]));
					}
				}
				
			}
		}

		// 处理path queue的最后一个元素
		let t_current_path_xpath_node = path_queue.pop();
		let t_children_queue_length = jq_obj_queue.length;
		for (let m = 0; m < t_children_queue_length; m++) {
			let jq_node = jq_obj_queue.pop();
			if (jq_node[0].tagName.toLowerCase() === t_current_path_xpath_node.tag_name.toLowerCase()){
				// 同名，该节点就是最终节点, 将该节点入队列
				jq_obj_queue.push(jq_node);
			}
			
		}
		
		// 遍历结束
		let result_obj = new Object();
		result_obj.num = jq_obj_queue.length;
		result_obj.list_xpath = jq_obj_queue.to_str_xpath_array();
		return result_obj;
	}

	/*
		返回xpath父节点的xpath
		param xpath:					目标xpath
		return:							xpath父节点的xpath
	*/
	get_xpath_patern(xpath){
		let jq_obj = this.xpath2jq(xpath);
		let parent_xpath = this.jq2xpath(jq_obj.parent(), false);
		return parent_xpath;
	}

	/*
		将id形式的xpath转换为全路径
	*/
	id_xpath_to_full_xpath(xpath){
		if (xpath === undefined || xpath === null || xpath === ""){
			return false;
		}
		let jq_tmp_obj = utility.xpath2jq(xpath);
		return utility.jq2xpath(jq_tmp_obj);
	}

	/*
		检测xpath是否在给定的max xpath里面
	*/
	is_xpath_in_max_path(xpath, max_xpath){
		let jq_xpath = utility.xpath2jq(xpath);
		let jq_max = utility.xpath2jq(max_xpath);
	
		while(1){
			if (jq_xpath.parent().is(jq_max) === true || jq_xpath.is(jq_max)){
				// 找到了, 验证成功
				return true;
			}

			jq_xpath = jq_xpath.parent();
			if (jq_xpath[0].tagName.toLowerCase() === "html"){
				// 找不到, 验证失败
				return false;
			}
		}
		return false;
	}

	/*
		返回浏览器的滑动位置
	*/
	get_ScrollTop(){
		return document.documentElement.scrollTop;
	}

	/*
		从当前位置，平滑移动到element
		:param element:      HtmlElement
        :param speed:        int
	*/
	animate_scroll_to_element(element, speed) {

        const UP = 1;
        const DOWN = -1;

        // let rect=element.getBoundingClientRect();
        let current_scrollTop = document.documentElement.scrollTop;
        let element_scrollTop = element.offset().top;
        let direction = UP;
        let requestId;

        // 判断移动方向
        if (current_scrollTop > element_scrollTop){
            // 向上移动
            direction = UP;
        }else{
            // 向下移动
            direction = DOWN;
        }

        //采用requestAnimationFrame，平滑动画
        function step(timestamp) {

            if (direction === UP){
                current_scrollTop -= speed;
                if (current_scrollTop >= element_scrollTop){
                    window.scrollTo(0, current_scrollTop);
                    requestId=window.requestAnimationFrame(step);
                }else{
                    window.cancelAnimationFrame(requestId);
                }
            }else{
                current_scrollTop += speed;
                if (current_scrollTop <= element_scrollTop){
                    window.scrollTo(0, current_scrollTop);
                    requestId=window.requestAnimationFrame(step);
                }else{
                    window.cancelAnimationFrame(requestId);
                }
            }
        }
        window.requestAnimationFrame(step);
	}

	/*
		从当前位置，平滑移动到指定位置
		:param scrollTop:      int
        :param speed:          int
	*/
	animate_scroll_to_poisition(scrollTop, speed){
		const UP = 1;
        const DOWN = -1;

        // let rect=element.getBoundingClientRect();
        let current_scrollTop = document.documentElement.scrollTop;
        let element_scrollTop = scrollTop;
        let direction = UP;
        let requestId;

        // 判断移动方向
        if (current_scrollTop > element_scrollTop){
            // 向上移动
            direction = UP;
        }else{
            // 向下移动
            direction = DOWN;
        }

        //采用requestAnimationFrame，平滑动画
        function step(timestamp) {

            if (direction === UP){
                current_scrollTop -= speed;
                if (current_scrollTop >= element_scrollTop){
                    window.scrollTo(0, current_scrollTop);
                    requestId=window.requestAnimationFrame(step);
                }else{
                    window.cancelAnimationFrame(requestId);
                }
            }else{
                current_scrollTop += speed;
                if (current_scrollTop <= element_scrollTop){
                    window.scrollTo(0, current_scrollTop);
                    requestId=window.requestAnimationFrame(step);
                }else{
                    window.cancelAnimationFrame(requestId);
                }
            }
        }
        window.requestAnimationFrame(step);
	}
	

}

class InspectorWithBorder{
	/*
		xpath显示器 - 边框显示
	*/

	constructor(){

		// obj{ori_border, xpath, xpath_type}
		this.list_data_binding_set = new Array();
		this.list_data_set = new Array();
		this.DATA_BINDING_TYPE_MAIN = 0;
		this.DATA_BINDING_TYPE_SUB = 1;
		this.DATA_BINDING_TYPE_MAX = 2;

		this.current_data_binding_xpath = null;
		this.current_data_binding_max = null;
	}

	/*
		预览所有标定元素

		!!!
		渲染的函数要尽可能快，不然页面效果会卡顿
	*/
	border_data_binding_set_xpath_element(xpath, xpath_type){
		// 检查是否有重复(交给外部函数处理 - 提高渲染速度)
		for (let i = 0; i < this.list_data_binding_set.length; i++) {
			const element = this.list_data_binding_set[i];
			// if (utility.xpath2jq(element.xpath).is(utility.xpath2jq(xpath)) === true){
			if (element.xpath === xpath){
				// 重复
				console.log("border_data_binding_set_xpath_element: 重复元素");
				return false;				
			}
		}

		// 设置边框
		let jq_obj = utility.xpath2jq(xpath);
		let list_obj = new Object();
		list_obj.ori_border = jq_obj.css("border");
		list_obj.ori_background_color = jq_obj.css("background-color");
		list_obj.xpath = xpath;
		list_obj.xpath_type = xpath_type;

		if (xpath_type === this.DATA_BINDING_TYPE_MAIN){
			jq_obj.attr("mw_xpath_type", this.DATA_BINDING_TYPE_MAIN);
			jq_obj.css("background-color", "rgba(237,102,99,0.5)")
			// jq_obj.css("border", "3px solid blue");
		}else if(xpath_type === this.DATA_BINDING_TYPE_SUB){
			jq_obj.attr("mw_xpath_type", this.DATA_BINDING_TYPE_SUB);
			// jq_obj.css("border", "3px solid yellow");
			jq_obj.css("background-color", "rgba(255,163,114,0.5)");
		}else if(xpath_type === this.DATA_BINDING_TYPE_MAX){
			jq_obj.attr("mw_xpath_type", this.DATA_BINDING_TYPE_MAX);
			// jq_obj.css("border", "3px solid red");
			jq_obj.css("background-color", "rgba(15,76,129,0.5)");
		}else{
			console.log("border_data_binding_set_xpath_element: error");
			return false;
		}

		// 缓存xpath
		this.list_data_binding_set.push(list_obj);
		return true;
	}

	// 清除所有标定元素的预览
	unborder_data_binding_set_xpath_element(){
		let list_length = this.list_data_binding_set.length
		for (let j = 0; j < list_length; j++) {
			const element = this.list_data_binding_set[j];
			let jq_obj = utility.xpath2jq(element.xpath);
			jq_obj.css("border", element.ori_border);
			jq_obj.css("background-color", element.ori_background_color);
		}

		// 清空数组
		for (let i = 0; i < list_length; i++) {
			this.list_data_binding_set.shift();
		}
	}

	// 预览所有的数据组
	border_data_set_xpath_element(xpath){
	}

	// 清除所有数据组的预览
	unborder_data_set_xpath_element(){

	}

	// 清除所有的预览
	unborder_all(){
		this.unborder_data_binding_set_xpath_element();
		this.unborder_data_set_xpath_element();
	}

	/*
		给指定元素改变样式~
		param jq_obj:		要套框的元素
		param css_style:	框框的样式s
	*/
	border_element(jq_obj, css_style="3px solid red"){
		if ((jq_obj instanceof jQuery) === false){
			console.log("==border element==");
			console.log("Error: argument is invalide");
			console.log("jq_obj:");
			console.log(jq_obj);
			return false;
		}

		jq_obj.css("border", css_style);
	}
}

// ==============
// 数据组
// ==============

/*
	数据组列表项
*/
class C_DataSet{
	
	static DATA_SET_TYPE_MAIN = 100;
	static DATA_SET_TYPE_MAX = 101;
	static DATA_SET_TYPE_SUB = 102;
	static DATA_SET_TYPE_TARGET = 103;
	static DATA_SET_TYPE_UNKNOWEN = 110;

	constructor(){
		// 基本值
		this.index = null;					// data_structure 中 DataSetList的下标
		this.xpath = null;
		this.jq_obj = null;

		// 样式表现
		this.ori_border_style = null;		// 弃用
		this.ori_css_style = new Object();
		this.preview_settings = {
			is_preview_border: false,
			is_preview_background_color: false,
			background_color: {
				"r": 237,
				"g": 102,
				"b": 99
			},
			border_color:{
				"r": 0,
				"g": 0,
				"b": 0
			}
		};

		// 状态值
		this.is_preview = false;			// 该数据组是否正在被预览
		this.is_data_binding_previewing = false;	// 数据绑定是否在预览这个元素
		this.is_data_set_previewing = false;		// 数据组是否在预览这个元素

		// 所属类型
		this.type = this.DATA_SET_TYPE_UNKNOWEN;					// 类型
	}

	// 初始化
	init_data_set(xpath, data_set_type, background_color, border_color, background_satus, border_status){
		this.xpath = xpath;
		this.jq_obj = utility.xpath2jq(xpath);
		this.ori_css_style.background_color = this.jq_obj.css("background-color");
		this.ori_css_style.border = this.jq_obj.css("border");
		this.data_set_type = data_set_type;

		this.preview_settings.background_color = background_color;
		this.preview_settings.border_color = border_color;

		this.preview_settings.is_preview_background_color = true;
		if (background_satus === true){
			this.preview_settings.is_preview_background_color = true;
		}else{
			this.preview_settings.is_preview_background_color = false;
		}

		if (border_status === true){
			this.preview_settings.is_preview_border = true;
		}else{
			this.preview_settings.is_preview_border = false;
		}
	}

	// 激活该元素的预览
	// active_preview(){
	// 	if (this.preview_settings.is_preview_background_color === true){
	// 	}

	// 	if (this.preview_settings.is_preview_border === true){

	// 	}
	// }

	active_main_preview(){
		if (this.type !== this.DATA_SET_TYPE_MAIN){
			console.log("==C_DataSet.active_main_preview==");
			console.log("Error: data set type error");
			console.log("type:");
			console.log(this.type);
			return false;
		}

		if (this.preview_settings.is_preview_background_color === true){
			// this.jq_obj.css("background-color", "rgba(237,102,99,0.5)");
			this.jq_obj.css("background-color", "rgba("+ this.preview_settings.background_color.r +","+ this.preview_settings.background_color.g +","+ this.preview_settings.background_color.b +",0.5)");
		}

		if (this.preview_settings.is_preview_border === true){
			this.jq_obj.css("border", "3px solid rgb("+ this.preview_settings.border_color.r +","+ this.preview_settings.border_color.g +","+ this.preview_settings.border_color.b +")");
		}

		return true;
	}

	active_max_preview(){
		if(this.type !== this.DATA_SET_TYPE_MAX){
			console.log("==C_DataSet.active_max_preview==");
			console.log("Error: data set type error");
			console.log("type:");
			console.log(this.type);
			return false;
		}

		if (this.preview_settings.is_preview_background_color === true){
			this.jq_obj.css("background-color", "rgba("+ this.preview_settings.background_color.r +","+ this.preview_settings.background_color.g +","+ this.preview_settings.background_color.b +",0.5)");
		}

		if (this.preview_settings.is_preview_border === true){
			this.jq_obj.css("border", "3px solid rgb("+ this.preview_settings.border_color.r +","+ this.preview_settings.border_color.g +","+ this.preview_settings.border_color.b +")");
		}

		return true;
	}

	active_sub_preview(){
		if (this.type !== this.DATA_SET_TYPE_SUB){
			console.log("==C_DataSet.active_sub_preview==");
			console.log("Error: data set type error");
			console.log("type:");
			console.log(this.type);
			return false;
		}

		if (this.preview_settings.is_preview_background_color === true){
			this.jq_obj.css("background-color", "rgba("+ this.preview_settings.background_color.r +","+ this.preview_settings.background_color.g +","+ this.preview_settings.background_color.b +",0.5)");
		}

		if (this.preview_settings.is_preview_border === true){
			this.jq_obj.css("border", "3px solid rgb("+ this.preview_settings.border_color.r +","+ this.preview_settings.border_color.g +","+ this.preview_settings.border_color.b +")");
		}

		return true;
	}

	active_target_preview(){
		if (this.type !== this.DATA_SET_TYPE_TARGET){
			console.log("==C_DataSet.active_sub_preview==");
			console.log("Error: data set type error");
			console.log("type:");
			console.log(this.type);
			return false;
		}

		if (this.preview_settings.is_preview_background_color === true){
		}

		if (this.preview_settings.is_preview_border === true){

		}
	}

	// 清除预览
	clear_preview(){
		if (this.preview_settings.is_preview_background_color === true){
			this.jq_obj.css("background-color", this.ori_css_style.background_color);
		}

		if (this.preview_settings.is_preview_border === true){
			this.jq_obj.css("border", this.ori_css_style.border);
		}

		return true;
	}

	set_ori_border_style(css_style){
		this.ori_border = css_style;
	}

	// 设置预览颜色
	set_preview_color(color, type){
		if (type === "background"){
			this.preview_settings.background_color.r = color.r;
			this.preview_settings.background_color.g = color.g;
			this.preview_settings.background_color.b = color.b;
		}else if(type === "border"){
			this.preview_settings.border_color.r = color.r;
			this.preview_settings.border_color.g = color.g;
			this.preview_settings.border_color.b = color.b;
		}
	}

	// 取消预览状态
	deactive_background_preview(){
		// 取消预览状态
		this.preview_settings.is_preview_background_color = false;		
	}

	deactivate_border_preview(){
		this.preview_settings.is_preview_border = false;
	}
}

/*
	数据绑定全局对象
*/
class C_DataBindingGlobal{
	constructor(){

		// 主要的最小结构 - C_DataSet
		this.main_node = new C_DataSet();

		// 最大范围 - C_DataSet
		this.max_node = new C_DataSet();

		// 生成的其他子结构 - C_DataSet
		this.sub_node_list = new Array();
	}

	/*
		初始化全局对象
		param xpath:主要的最小结构 - xpath
		param max_xpath:最大范围 - xpath
		param sub_xpath_list:生成的结构 - array

		** sub_xpath_list可能包含了xpath本身, 为了方便后面的处理, 这里要先对这个list做清理,剔除了这个重复的xpath
	*/
	init_global(xpath, max_xpath, sub_xpath_list, colors, status){
		this.reset_global();

		this.main_node.init_data_set(
			xpath, 
			C_DataSet.DATA_SET_TYPE_MAIN, 
			colors.color_data_binding_background, 
			colors.color_data_binding_border,
			status.data_binding_background,
			status.data_binding_border);

		this.max_node.init_data_set(
			max_xpath, 
			C_DataSet.DATA_SET_TYPE_MAX,
			colors.color_max_background,
			colors.color_max_border,
			status.max_background,
			status.max_border);

		// 清洗sub_xpath_list
		for (let i = 0; i < sub_xpath_list.length; i++) {
			const element = sub_xpath_list[i];
			if (element === xpath){
				// 找到了, 删除
				sub_xpath_list.splice(i, 1);
				break;
			}
		}

		for (let j = 0; j < sub_xpath_list.length; j++) {
			const element = sub_xpath_list[j];
			let new_sub_node = new C_DataSet();
			new_sub_node.init_data_set(
				element, 
				C_DataSet.DATA_SET_TYPE_SUB,
				colors.color_sub_background,
				colors.color_sub_border,
				status.sub_background,
				status.sub_border);
			this.sub_node_list.push(new_sub_node);
		}
		return true;
	}

	// 重置全局对象
	reset_global(){
		this.main_node = new C_DataSet();
		this.max_node = new C_DataSet();
		this.sub_node_list = new Array();
	}

	// 激活预览
	active_preview(){
		console.log("==C_DataBindingGlobal.active_preview==");
		// 检查是否完成初始化
		if (this.main_node === null || this.main_node === undefined){
			console.log("Error");
			console.log("data binding global is not init yet");
			return false;
		}

		this.main_node.active_main_preview();
		this.max_node.active_max_preview();
		for (let i = 0; i < this.sub_node_list.length; i++) {
			const element = this.sub_node_list[i];
			element.active_sub_preview();
		}
		return true;
	}

	// 清除和数据绑定相关的所有预览
	clear_all_preview(){
		console.log("==C_DataBindingGlobal.clear_all_preview==");
		if (this.main_node){
			this.main_node.clear_preview();
		}

		if (this.max_node){
			this.max_node.clear_preview()
		}

		for (let i = 0; i < this.sub_node_list.length; i++) {
			const element = this.sub_node_list[i];
			element.clear_preview();
		}
		return true;
	}

	// 刷新预览样式
	refresh_preview(node, type, color){
		if (node === "data_binding"){
			this.main_node.set_preview_color(color, type);
		}else if(node === "max"){
			this.max_node.set_preview_color(color, type);
		}else if(node === "sub"){
			for (let i = 0; i < this.sub_node_list.length; i++) {
				const node = this.sub_node_list[i];
				node.set_preview_color(color, type);
			}
		}

		this.active_preview();
	}
}

/*
	数据组列表
*/
class C_DataSetList{
	constructor(){
		this.list_space = new Array();
		this.list_length = 0;
		this.list_size = 20;
	}

	// 获取列表中第i个元素
	get_data_set(i){
		if (i > this.list_length || i < 1){
			return false;
		}else{
			return this.list_space[i-1];
		}
	}

	// 获取列表中, 列表项的index属性值为index的数据组, 如果没有返回false
	get_data_set_by_index(index){
		for (let i = 0; i < this.list_length; i++) {
			const element = this.list_space[i];
			if (element.index === index){
				return element;
			}
		}

		return false
	}

	// 根据列表项index属性值为index的数据组,返回其在列表中的序号
	get_i_by_index(index){
		for (let i = 0; i < this.list_length; i++) {
			const element = this.list_space[i];
			if (element.index === index){
				return i+1;
			}
		}

		// 找不到
		return false;
	}

	// 插入一个新的元素到列表末尾
	insert_data_set(c_data_set){
		if (c_data_set.index !== null && c_data_set !== undefined){
			this.list_space.push(c_data_set);
			this.list_length++;
			return true;
		}else{
			console.log("Insert data set Error");
			console.log("c_data_set:");
			console.log(c_data_set);
			return false
		}
	}

	// 删除第i个元素
	delete_data_set(i){
		if (i < 1 || i > this.list_length){
			return false;
		}

		this.list_space.splice(i-1, i);
		return true;
	}
}

/*
	数据组全局对象
*/
class C_DataSetGlobal{
	constructor(){
		this.active_data_set_list = new C_DataSetList();					// 当前激活了预览的数据组列表
	}

	// =============
	// 页面逻辑相关函数
	// =============

	// 插入新的dataset到列表,并预览它
	active_preview_data_set(index, xpath){
		/*
			:param index: 数据组在devtool的下标
			:param xpath: 数据组的xpath
		*/
		console.log("==active_preview_data_set==")

		// 创建一个新的节点,并插入
		let new_data_set = new C_DataSet();
		new_data_set.index = index;
		new_data_set.xpath = xpath;
		let jq_obj = utility.xpath2jq(xpath);
		new_data_set.jq_obj = jq_obj;
		if (this.active_data_set_list.insert_data_set(new_data_set) === false){
			return false;
		}

		// 缓存节点原来的css样式
		this.save_ori_css(this.active_data_set_list.list_length);

		// 改变html表现
		let id = this.active_data_set_list.get_i_by_index(index);
		this.border_data_set(id);
		// inspect_with_border.border_element(new_data_set.jq_obj);
		// new_data_set.is_preview = true;

	}

	// 取消预览属性index值为index的节点
	deactive_preview_data_set(index){
		console.log("==deactive_preview_data_set==");

		// 找到该节点
		let element = this.active_data_set_list.get_data_set_by_index(index);

		if (element === false){
			// 找不到
			return false;
		}

		// 改变html表现
		let id = this.active_data_set_list.get_i_by_index(index);
		if (id === false){
			return false;
		}
		this.unborder_data_set(id);
		
		// 删除该元素
		this.active_data_set_list.delete_data_set(id);
		this.active_data_set_list.list_length--;

	}


	// =============
	// 元素表现
	// =============

	/*
		预览数据组列表中,第i个数据组
	*/
	border_data_set(i){
		// 校验i的合法性
		if (i < 1 || i > this.active_data_set_list.list_size){
			console.log("==border_data_set==");
			console.log("index is invalide");
			return false;
		}

		let element = this.active_data_set_list.list_space[i-1];

		// 检查元素是否有冲突的渲染
		if (element.is_preview === true){
			// 该元素已经被预览
			console.log("元素已经被预览");
			return false;
		}else{
			this.active_data_set_list.list_space[i-1].is_preview = true;
		}

		// 套框
		inspect_with_border.border_element(element.jq_obj);
	}

	/*
		缓存第i个节点原本的css样式
	*/
	save_ori_css(i){
		if (i < 1 || i > this.active_data_set_list.list_length){
			console.log("==save_ori_css==");
			console.log("index is invalide");
			return false;
		}

		let element = this.active_data_set_list.list_space[i-1];

		this.active_data_set_list.list_space[i-1].set_ori_border_style(element.jq_obj.css("border"));
		return true;
	}

	/*
		取消预览数据组列表中,第i个数据组
	*/
	unborder_data_set(i){
		/*
			:param i:	data set在active list的下标
		*/
		if (i < 1 || i > this.active_data_set_list.list_length){
			console.log("==unborder_data_set==");
			console.log("index is invalide");
			return false;
		}

		let element = this.active_data_set_list.list_space[i-1];

		// 改变html表现
		if (element.ori_border === null || element.ori_border === undefined){
			inspect_with_border.border_element(element.jq_obj, "");
		}else{
			inspect_with_border.border_element(element.jq_obj, element.ori_border);
		}
	}

}

const inspect = new Inspector();
// const preview = new Preview();
const utility = new Utility();
const inspect_with_border = new InspectorWithBorder();
const c_data_set_global = new C_DataSetGlobal();
const c_data_binding_global = new C_DataBindingGlobal();


function get_simple_list_table_data(request){
	let data_binding_xpath = request.data_binding_xpath;
	let data_binding_sub_list = request.data_binding_sub_list;
	let data_set_list = request.data_set_list;

	/*
		result_list: [['xpath or null', 'xpath or null', ...], ...]
	*/
	let result_list = new Array();

	// 初始化 result_list
	for (let index = 0; index < data_binding_sub_list.length; index++) {
		let new_obj = new Array();
		result_list.push(new_obj);
	}

	for (let i = 0; i < data_set_list.length; i++) {
		const data_set = data_set_list[i];
		
		// 构造路径
		let xpath = data_set.target_xpath.split(data_binding_xpath)[1];
		let xpath_list = xpath.split("/");
		xpath_list.shift();

		let xpath_node_list = new Array();
		for (let j = 0; j < xpath_list.length; j++) {
			let new_xpath_node = new XpathNode();
			new_xpath_node.string_to_xath_node_obj(xpath_list[j]);
			xpath_node_list.push(new_xpath_node);
		}

		// 获取数据
		for (let k = 0; k < data_binding_sub_list.length; k++) {
			const data_binding_sub_xpath = data_binding_sub_list[k];
			let jq_sub = utility.xpath2jq(data_binding_sub_xpath);
			let children_list = jq_sub.children();
			let is_found = false;

			for (let l = 0; l < xpath_node_list.length; l++) {

				is_found = false;
				
				if (xpath_node_list[l].has_same_brother === false){
					for (let m = 0; m < children_list.length; m++) {
						if (children_list[m].tagName.toLowerCase() === xpath_node_list[l].tag_name.toLowerCase()){
							jq_sub = $(children_list[m]);
							children_list = jq_sub.children();
							is_found = true;
							break;
						}
						
					}

				}else if(xpath_node_list[l].has_same_brother === true){
					let counter = 1;
					for (let n = 0; n < children_list.length; n++) {
						if (children_list[n].tagName.toLowerCase() === xpath_node_list[l].tag_name.toLowerCase()){
							if (counter === xpath_node_list[l].index){
								jq_sub = $(children_list[n]);
								children_list = jq_sub.children();
								is_found = true;
								break;
							}else{
								counter++;
							}
						}
					}
				}

				if (is_found === false){
					break;
				}
			}

			// 走完所有路径,
			// 此处完成了单个sub+单个data_set的寻找
			if (is_found === false){
				result_list[k][i] = '';
			}else{
				result_list[k][i] = jq_sub.text();
			}
			
		}

		// 此处完成了单个data_set+所有sub的寻找
	}
	
	// 此处完成了所有的寻找
	console.log("===result list===");
	console.log(result_list);

	let return_obj = new Object();
	return_obj.todo = "get_table_data";
	return_obj.msg_type = MSG_NORMAL;
	return_obj.data_list = result_list;
	return_obj.sub_xpath_list = data_binding_sub_list;
	chrome.runtime.sendMessage(return_obj);
}

function stop_get_data(){
	let return_obj = new Object();
	return_obj.todo = "stop_get_data";
	return_obj.msg_type = MSG_NORMAL;
	// return_obj.data_list = result_list;
	// return_obj.sub_xpath_list = data_binding_sub_list;
	chrome.runtime.sendMessage(return_obj);
}

/*
==========================
最重要的监听器
监听来自background的消息
==========================
*/
chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
    if(request.todo == "changeColor"){
        var addColor = '#' + request.clickColor;
        $('.api').css('color', addColor);
    }else if(request.todo == "test"){
        console.log(request.text);
    }else if(request.todo == "getDataBindingXpath"){
		console.log("==getDataBindingXpath==");
		// 检查Inspector状态
		if (inspect_status === INSPECTOR_STATUS_ON){
			// inspector 正在被占用
			if (current_action !== INSPECTOR_CURRENT_DATA_BINDING_XPATH && current_action !== INSPECTOR_CURRENT_FREE){
				// 占用的不是 data binding xpath
				/*
					1. 将当前的占用对象改为data binding xpath
					2. 设置inspect变量
				*/
				console.log("==转换inspector占用状态==");
				console.log("ori:" + current_action);
				current_action = INSPECTOR_CURRENT_DATA_BINDING_XPATH;
				inspect.is_lock_max = request.is_lock_max;
				inspect.lock_max = request.lock_max;
				inspect.current_msg = request;
				console.log("current:" + current_action);
			}else{
				// 占用的是 data binding xpath
				/*
					1. 取消 inspector的激活状态
					2. 重置 inspector的状态值和占用对象
				*/

				if (inspect.current_msg.todo_type !== request.todo_type){
					// data binding 里面其他按钮进行xpath请求
					// 不更改current action， 只改变量
					inspect.is_lock_max = request.is_lock_max;
					inspect.lock_max = request.lock_max;
					inspect.current_msg = request;
				}else{
					// data binidng 里面相同的按钮进行请求
					console.log("==关闭inspector==");
					console.log("ori:" + current_action);
					inspect.deactivate();
					inspect_status = INSPECTOR_STATUS_OFF;
					current_action = INSPECTOR_CURRENT_FREE;
					inspect.init_lock_max();
					console.log("current:" + current_action);
				}
			}
		}else if (inspect_status == INSPECTOR_STATUS_OFF){
			// inspector 没有被占用
			/*
				1. 激活 inspector
				2. 改变 inspector的状态值和占用对象
			*/
			console.log("==激活inspector==");
			console.log("ori:" + current_action);
			inspect.getOptions();
			inspect_status = INSPECTOR_STATUS_ON;
			current_action = INSPECTOR_CURRENT_DATA_BINDING_XPATH;
			inspect.is_lock_max = request.is_lock_max;
			inspect.lock_max = request.lock_max;
			inspect.current_msg = request;
			console.log("current:" + current_action);
		}
    }else if(request.todo == "preview"){
        console.log("==content=preview");
        if(request.xpath){
			data_binding_preview_status = -data_binding_preview_status;

			if(data_binding_preview_status == 1){
				preview.activate(request.xpath);
			}else{
				preview.deactivate();
			}
        }else{
			console.log("xpath empty");
		}
    }else if(request.todo == "getBasicInfo"){
		console.log("==content=getBasicInfo");
		let url = window.location.href;
		// 这种方法获取的cookie信息不完整
		// let cookies = chrome.cookies.getAll({url: url});
		// let cookies = document.cookie
		let msg = {
			url: url
			// cookies: cookies
		}
		chrome.runtime.sendMessage({todo: "basicInfo", basicInfo: msg}, function(response) {
            console.log("send success and get response");
        });
    }else if(request.todo == "getMaxRange"){
		// 检查inspector状态
		if (inspect_status === INSPECTOR_STATUS_ON){
			// inspector已经被激活
			if (current_action !== INSPECTOR_CURRENT_DATA_BINDING_MAX_XPATH && current_action !== INSPECTOR_CURRENT_FREE){
				// INSPECTOR 不是被max path占用
				/*
					1. 将当前的占用对象改为data binding max path
				*/
				console.log("==转换inspector占用状态==");
				console.log("ori:" + current_action);
				current_action = INSPECTOR_CURRENT_DATA_BINDING_MAX_XPATH;
				console.log("current:" + current_action);
			}else{
				// inspector 被max path占用
				/*
					1. 取消 inspector的激活状态
					2. 重置 inspector的状态值和占用对象
				*/
				console.log("==转换inspector占用状态==");
				console.log("ori:" + current_action);
				inspect.deactivate();
				inspect_status = INSPECTOR_STATUS_OFF;
				current_action = INSPECTOR_CURRENT_FREE;
				console.log("current:" + current_action);
			}

		}else if (inspect_status === INSPECTOR_STATUS_OFF){
			// inspector 没有被占用
			/*
				1. 激活 inspector
				2. 改变 inspector的状态值和占用对象
			*/
			console.log("==转换inspector占用状态==");
			console.log("ori:" + current_action);
			inspect.getOptions();
			inspect_status = INSPECTOR_STATUS_ON;
			current_action = INSPECTOR_CURRENT_DATA_BINDING_MAX_XPATH;
			console.log("current:" + current_action);
		}
	}else if(request.todo == "getSubRange"){
		// 弃用
		current_action = 'GetSubRangeXpath'
		console.log("==content=getSubRange==");
		inspect_status = -inspect_status;
		if(inspect_status == 1){
			console.log("getSubRange");
			inspect.getOptions();
		}else if(inspect_status == -1){
			inspect.deactivate();
		}
	}else if(request.todo === "autoSubRange"){
		// this is a test
		console.log("content: auto sub range start");

		// 获取自动生成的子结构xpath
		let = result_obj = utility.autoSubRange(request.xpath, request.max_range_xpath);

		// 显示xpath(边框)
		let list_sub_range_xpath = result_obj['list_sub_range_xpath'];

		for (let index = 0; index < list_sub_range_xpath.length; index++) {
			const xpath = list_sub_range_xpath[index];
			inspect_with_border.border_xpath_element(xpath)	;
		}

		console.log(result_obj);
		console.log("content: auto sub range end");
  	}else if(request.todo === "activePreview"){
		// 弃用
      	console.log("active preview: start");
      	let bingding_data_set = request.bingding_data_set;
      	let data_set_list = request.data_set_list;

		// 显示标定数据
		inspect_with_border.border_xpath_element(bingding_data_set.xpath_binding);
    }else if(request.todo === "activeBindingDataPreview"){
		console.log("==activeBindingDataPreview==");
		console.log(request);

		if (c_data_binding_global.clear_all_preview() === false){
			console.log("==activeBindingDataPreview==");
			console.log("Error");
			return false;
		}

		c_data_binding_global.init_global(
			request.data_binding_set.xpath_binding,
			request.data_binding_set.max_xpath_binding,
			request.data_binding_set.sub_xpath_binding_list,
			request.colors,
			request.status
		);

		c_data_binding_global.active_preview();
	}else if(request.todo === "deactiveBindingDataPreview"){
		console.log("==deactiveBindingDataPreview==");


		c_data_binding_global.clear_all_preview();

		// 弃用
		// inspect_with_border.unborder_data_binding_set_xpath_element();
	}else if(request.todo === "adjust_max_xpath_up"){
		console.log("==adjust_max_xpath_up==");
		let return_obj = new Object();
		return_obj.todo = "adjust_max_xpath_up";
		return_obj.msg_type = MSG_NORMAL;

		let jq_obj = utility.xpath2jq(request.max_range_xpath);
		// 判断当前的obj是不是html
		if (jq_obj[0].tagName.toLowerCase() === "body"){
			// 返回原来的xpath
			return_obj.max_range_xpath = request.max_range_xpath;
			return_obj.is_success = -1;
		}else{
			let jq_parent_obj = jq_obj.parent();
			if (jq_parent_obj.length === 0){
				// 返回原来的xpath
				return_obj.max_range_xpath = request.max_range_xpath;
				return_obj.is_success = -1;
			}else{
				// 存在合法的父节点
				let jq_parent_xpath = utility.jq2xpath(jq_parent_obj);

				// 获取新的子结构
				let request_obj = utility.autoSubRange(request.xpath ,jq_parent_xpath);
				let list_sub_range_xpath = request_obj.list_sub_range_xpath;

				// 设置返回变量
				return_obj.xpath = request.xpath;
				return_obj.max_range_xpath = jq_parent_xpath;
				return_obj.is_success = 1;
				return_obj.list_sub_range_xpath = list_sub_range_xpath;
			}
		}
		chrome.runtime.sendMessage(return_obj);
	}else if(request.todo === "adjust_max_xpath_down"){
		console.log("==adjust_max_xpath_down==");
		let return_obj = new Object();
		return_obj.todo = "adjust_max_xpath_down";
		return_obj.msg_type = MSG_NORMAL;

		let jq_max_range = utility.xpath2jq(request.max_range_xpath);
		// 判断max xpath是否到了下限（reqeut.xpath的父节点）
		let jq_xpath = utility.xpath2jq(request.xpath);
		let jq_xpath_parent = jq_xpath.parent();
		if (jq_max_range.is(jq_xpath_parent)){
			// 返回原来的xpath
			return_obj.max_range_xpath = request.max_range_xpath;
			return_obj.is_success = -1;
		}else{
			let jq_target = jq_xpath;
			while(1){
				if (jq_target.parent().is(jq_max_range)){
					// 找到了目标节点
					let jq_target_xpath = utility.jq2xpath(jq_target);

					let request_obj = utility.autoSubRange(request.xpath ,jq_target_xpath);
					let list_sub_range_xpath = request_obj.list_sub_range_xpath;

					return_obj.xpath = request.xpath;
					return_obj.max_range_xpath = jq_target_xpath;
					return_obj.is_success = 1;
					return_obj.list_sub_range_xpath = list_sub_range_xpath;
					break;
				}

				jq_target = jq_target.parent();

				if (jq_target[0].tagName === "body"){
					// error 找不到tag
					// 返回原来的xpath
					return_obj.max_range_xpath = request.max_range_xpath;
					return_obj.is_success = -1;
					break;
				}

			}
		}

		chrome.runtime.sendMessage(return_obj);
	}else if(request.todo === "adjust_binding_xpath_up"){
		console.log("==adjust_binding_xpath_up==");
		let return_obj = new Object();
		return_obj.todo = "adjust_binding_xpath_up";
		return_obj.msg_type = MSG_NORMAL;

		let jq_xpath = utility.xpath2jq(request.xpath);
		let jq_max_xpath = utility.xpath2jq(request.max_range_xpath);

		// 边界处理
		if (jq_xpath.parent()[0].tagName.toLowerCase() === "body"){
			// 达到最大边界
			return_obj.xpath = request.xpath;
			return_obj.max_range_xpath = request.max_range_xpath;
			return_obj.is_success = -1;
		}else if (jq_xpath.parent().is(jq_max_xpath)){
			// 没有到最大边界，但是到了最大范围
			// 检查是否有锁定最大范围
			if (request.is_lock_max === 1){
				// 锁定了
				return_obj.is_success = -1;
			}else{
				// 没有锁定
				// xpath和max各上一级
				return_obj.xpath = utility.jq2xpath(jq_xpath.parent());
				return_obj.max_range_xpath = utility.jq2xpath(jq_max_xpath.parent());
				return_obj.is_success = 1;
				let request_obj = utility.autoSubRange(return_obj.xpath ,return_obj.max_range_xpath);
				let list_sub_range_xpath = request_obj.list_sub_range_xpath;
				return_obj.list_sub_range_xpath = list_sub_range_xpath;
			}
		}else{
			// 既没有到最大边界 也没有到最大范围
			return_obj.xpath = utility.jq2xpath(jq_xpath.parent());
			return_obj.max_range_xpath = request.max_range_xpath;
			return_obj.is_success = 1;

			let request_obj = utility.autoSubRange(return_obj.xpath ,return_obj.max_range_xpath);
			let list_sub_range_xpath = request_obj.list_sub_range_xpath;
			return_obj.list_sub_range_xpath = list_sub_range_xpath;
		}

		chrome.runtime.sendMessage(return_obj);
	}else if(request.todo === "adjust_binding_xpath_down"){
		console.log("==adjust_binding_xpath_down==");
		let return_obj = new Object();
		return_obj.todo = "adjust_binding_xpath_down";
		return_obj.msg_type = MSG_NORMAL;

		let jq_xpath = utility.xpath2jq(request.xpath);
		let jq_xpath_ori = utility.xpath2jq(request.xpath_ori);

		// 边界处理
		if (jq_xpath.is(jq_xpath_ori) === true){
			// 一开始就是最小边界
			return_obj.xpath = request.xpath;
			return_obj.max_range_xpath = request.max_range_xpath;
			return_obj.is_success = -1;
		}else{
			// 不是最小边界
			let jq_target = jq_xpath_ori;
			while(1){
				if (jq_target.parent().is(jq_xpath) === true){
					// 找到了
					return_obj.xpath = utility.jq2xpath(jq_target);
					return_obj.max_range_xpath = request.max_range_xpath;
					return_obj.is_success = 1;

					let request_obj = utility.autoSubRange(return_obj.xpath ,request.max_range_xpath);
					let list_sub_range_xpath = request_obj.list_sub_range_xpath;
					return_obj.list_sub_range_xpath = list_sub_range_xpath;
					break;
				}

				jq_target = jq_target.parent();
				if (jq_target[0].tagName.toLowerCase() === "html"){
					// 找不到
					return_obj.xpath = request.xpath;
					return_obj.max_range_xpath = request.max_range_xpath;
					return_obj.is_success = -1;
					break;
				}
			}
		}
		chrome.runtime.sendMessage(return_obj);
	}else if(request.todo === "getSubWithSelectedData"){
		console.log("==getSubWithSelectedData==");
		let return_obj = new Object();
		return_obj.todo = "getSubWithSelectedData";
		return_obj.msg_type = MSG_NORMAL;
		let request_obj = utility.autoSubRange(request.xpath, request.max_range_xpath);
		let list_sub_range_xpath = request_obj.list_sub_range_xpath;
		
		return_obj.list_sub_range_xpath = list_sub_range_xpath;
		return_obj.xpath = request.xpath;
		return_obj.max_data_binding_xpath = request.max_range_xpath;
		chrome.runtime.sendMessage(return_obj);
	}else if(request.todo === "check_xpath_and_lock_max_xpath"){
		console.log("==check_xpath_and_lock_max_xpath==");
		let return_obj = request;
		let jq_xpath = utility.xpath2jq(request.xpath);
		let jq_max = utility.xpath2jq(request.lock_max);

		while(1){
			if (jq_xpath.parent().is(jq_max) === true){
				// 找到了, 验证成功
				return_obj.is_success = 1;
				break;
			}

			jq_xpath = jq_xpath.parent();
			if (jq_xpath[0].tagName.toLowerCase() === "html"){
				// 找不到, 验证失败
				return_obj.is_success = -1;
				break;
			}
		}
		chrome.runtime.sendMessage(return_obj);
	}else if(request.todo === "getTargetValue"){
		// 获取数据组的数据
		console.log("==getTragetValue==");

		// 检查Inspector状态
		if (inspect_status === INSPECTOR_STATUS_ON){
			// inspector 被占用
			if (current_action !== INSPECTOR_CURRENT_TARGET_DATA && current_action !== INSPECTOR_CURRENT_FREE){
				// 不是自己在占用
				// 将当前的占用对象改为 target value
				console.log("==转换inspector占用状态==");
				console.log("ori:" + current_action);
				current_action = INSPECTOR_CURRENT_TARGET_DATA;
				inspect.current_msg = request;
				console.log("current:" + current_action);
			}else{
				// 是自己在占用
				// 取消inspector的激活状态
				console.log("==转换inspector占用状态==");
				console.log("ori:" + current_action);
				inspect.deactivate();
				inspect_status = INSPECTOR_STATUS_OFF;
				current_action = INSPECTOR_CURRENT_FREE;
				// 初始化变量
				inspect.init_current_msg();
				console.log("current:" + current_action);
			}

		}else if (inspect_status === INSPECTOR_STATUS_OFF){
			// 激活inspector
			console.log("==激活inspector==");
			console.log("ori:" + current_action);
			inspect.current_msg = request;
			inspect.getOptions();
			inspect_status = INSPECTOR_STATUS_ON;
			current_action = INSPECTOR_CURRENT_TARGET_DATA;
			console.log("current:" + current_action);
		}
	}else if(request.todo === "activeDataSetPreview"){
		// 激活数据组预览
		c_data_set_global.active_preview_data_set(request.index, request.xpath);
	}else if(request.todo === "deactiveDataSetPreview"){
		// 取消激活数据组预览
		c_data_set_global.deactive_preview_data_set(request.index);
	}else if(request.todo === "getDataContinues"){
		console.log("==getDataContinues==");
		if (inspect_status === INSPECTOR_STATUS_ON){
			if (current_action !== INSPECTOR_CURRENT_CONTINUES && current_action !== INSPECTOR_CURRENT_FREE){
				console.log("==转换inspector占用状态==");
				console.log("ori:" + current_action);
				current_action = INSPECTOR_CURRENT_CONTINUES;
				inspect.current_msg = request;
				console.log("current:" + current_action);
			}else{
				console.log("==关闭inspector==");
				console.log("ori:" + current_action);
				inspect.deactivate();
				inspect_status = INSPECTOR_STATUS_OFF;
				current_action = INSPECTOR_CURRENT_FREE;
				inspect.init_lock_max();
				console.log("current:" + current_action);
			}
		}else if(inspect_status === INSPECTOR_STATUS_OFF){
			console.log("==激活inspector==");
			console.log("ori:" + current_action);
			inspect.getOptions();
			inspect_status = INSPECTOR_STATUS_ON;
			current_action = INSPECTOR_CURRENT_CONTINUES;			
			inspect.current_msg = request;
			console.log("current:" + current_action);
		}
	}else if(request.todo === "refresh_viewer"){
		// 生成十字链表
		let cross_list = new CrossList();
		let full_xpath = request.xpath;
		let return_obj = new Object();
		cross_list.root = utility.xpath2jq(full_xpath);
		cross_list.generate_list_space();
		cross_list.generate_node_space();
		cross_list.transform_list();
		console.log("List Space:");
		console.log(cross_list.list_space);

		console.log("Node Space:");
		console.log(cross_list.node_space);
		// cross_list
		return_obj.cross_list_space = cross_list.list_space;
		return_obj.cross_node_space = cross_list.node_space;
		return_obj.todo = "refresh_viewer";
		return_obj.msg_type = MSG_NORMAL;


		chrome.runtime.sendMessage(return_obj);	
	}else if(request.todo === "get_table_data"){
		get_simple_list_table_data(request);
	}else if(request.todo === "get_table_data_structure"){
		let data_binding_xpath = request.data_binding_xpath;
		let data_binding_sub_list = request.data_binding_sub_list;
		let structure_list = request.structure;

		/*
			result_list: [['xpath or null', 'xpath or null', ...], ...]
		*/
		let result_list = new Array();

		// 初始化 result_list
		for (let index = 0; index < data_binding_sub_list.length; index++) {
			let new_obj = new Array();
			result_list.push(new_obj);
		}

		for (let i = 0; i < structure_list.length; i++) {
			const data_set = structure_list[i];
			
			// 构造路径
			let xpath = data_set.xpath;
			let xpath_list = xpath.split("/");
			xpath_list.shift();
			xpath_list.shift();

			let xpath_node_list = new Array();
			for (let j = 0; j < xpath_list.length; j++) {
				let new_xpath_node = new XpathNode();
				new_xpath_node.string_to_xath_node_obj(xpath_list[j]);
				xpath_node_list.push(new_xpath_node);
			}

			// 获取数据
			for (let k = 0; k < data_binding_sub_list.length; k++) {
				const data_binding_sub_xpath = data_binding_sub_list[k];
				let jq_sub = utility.xpath2jq(data_binding_sub_xpath);
				let children_list = jq_sub.children();
				let is_found = false;

				for (let l = 0; l < xpath_node_list.length; l++) {

					is_found = false;
					
					if (xpath_node_list[l].has_same_brother === false){
						for (let m = 0; m < children_list.length; m++) {
							if (children_list[m].tagName.toLowerCase() === xpath_node_list[l].tag_name.toLowerCase()){
								jq_sub = $(children_list[m]);
								children_list = jq_sub.children();
								is_found = true;
								break;
							}
							
						}

					}else if(xpath_node_list[l].has_same_brother === true){
						let counter = 1;
						for (let n = 0; n < children_list.length; n++) {
							if (children_list[n].tagName.toLowerCase() === xpath_node_list[l].tag_name.toLowerCase()){
								if (counter === xpath_node_list[l].index){
									jq_sub = $(children_list[n]);
									children_list = jq_sub.children();
									is_found = true;
									break;
								}else{
									counter++;
								}
							}
						}
					}

					if (is_found === false){
						break;
					}
				}

				// 走完所有路径,
				// 此处完成了单个sub+单个data_set的寻找
				if (is_found === false){
					result_list[k][i] = '';
				}else{
					let new_array = new Array();
					for (let v = 0; v < structure_list[i].selected_attr_list.length; v++) {
						const attr = structure_list[i].selected_attr_list[v];
						if (jq_sub.attr(attr.name) !== undefined){
							new_array.push(jq_sub.attr(attr.name));
						}else if (attr.name === "mc_text"){
							new_array.push(jq_sub.text());
						}
					}
					result_list[k][i] = new_array;
				}
				
			}

			// 此处完成了单个data_set+所有sub的寻找
		}
		
		// 此处完成了所有的寻找
		console.log("===result list===");
		console.log(result_list);

		let return_obj = new Object();
		return_obj.todo = "get_table_data_structure";
		return_obj.msg_type = MSG_NORMAL;
		return_obj.data_list = result_list;
		chrome.runtime.sendMessage(return_obj);
	}else if(request.todo === "turn_page_and_get_data"){

		let btn_xpath = request.btn_xpath;
		let jq_btn = utility.xpath2jq(btn_xpath);
		let btn_scrollTop = request.btn_scrollTop;
		let turn_page_rate = Number(request.turn_page_rate) * 1000;

		// 滑动到底部
		// let bottom_dist = document.documentElement.scrollHeight || document.body.scrollHeight;
		// window.scrollTo(0,bottom_dist);
		// window.scrollTo(0, btn_scrollTop);

		let btn_new = $("#mc_data");
		if (btn_new.length === 0){

			if (jq_btn === false){
				stop_get_data();
			}

			jq_btn.attr("id","mc_data");
			jq_btn[0].click();
			// utility.animate_scroll_to_poisition(btn_scrollTop, 500);
			utility.animate_scroll_to_element(jq_btn, 500);
			// window.scrollTo(0, btn_scrollTop);
		}else{
			btn_new[0].click();
			// utility.animate_scroll_to_poisition(btn_scrollTop, 500);
			utility.animate_scroll_to_element(btn_new, 500);
			// window.scrollTo(0, btn_new.offset().top);
		}

		setTimeout(function(){
			if (btn_new.length === 0){
				// utility.animate_scroll_to_poisition(btn_scrollTop, 100);
				utility.animate_scroll_to_element(jq_btn, 500);
			}else{
				// utility.animate_scroll_to_poisition(btn_scrollTop, 100);
				utility.animate_scroll_to_element(btn_new, 500);
			}

			// 获取新加载的数据
			let request_obj = utility.autoSubRange(request.data_binding_xpath, request.data_binding_max);

			request.data_binding_sub_list = request_obj.list_sub_range_xpath;
			get_simple_list_table_data(request);
		}, turn_page_rate);
	}else if(request.todo === "get_waterfall_data"){
		let bottom_dist = document.documentElement.scrollHeight || document.body.scrollHeight;
		window.scrollTo(0,bottom_dist);

		setTimeout(function(){
			// 获取新加载的数据
			let request_obj = utility.autoSubRange(request.data_binding_xpath, request.data_binding_max);

			request.data_binding_sub_list = request_obj.list_sub_range_xpath;
			get_simple_list_table_data(request);
		}, turn_page_rate);

	}else if(request.todo === "get_waterfall_btn_data"){
		let btn_xpath = request.btn_xpath;
		let jq_btn = utility.xpath2jq(btn_xpath);
		// let btn_scrollTop = request.btn_scrollTop;
		let turn_page_rate = Number(request.turn_page_rate) * 1000;

		// 滑动到底部
		let bottom_dist = document.documentElement.scrollHeight || document.body.scrollHeight;
		// window.scrollTo(0,bottom_dist);
		// window.scrollTo(0, btn_scrollTop);

		let btn_new = $("#mc_data");
		if (btn_new.length === 0){

			if (jq_btn === false){
				stop_get_data();
			}

			jq_btn.attr("id","mc_data");
			jq_btn[0].click();
			utility.animate_scroll_to_poisition(bottom_dist, 1000);
			// utility.animate_scroll_to_element(jq_btn, 1000);
			// window.scrollTo(0, btn_scrollTop);
		}else{
			btn_new[0].click();
			utility.animate_scroll_to_poisition(bottom_dist, 1000);
			// utility.animate_scroll_to_element(btn_new, 1000);
			// window.scrollTo(0, btn_new.offset().top);
		}

		setTimeout(function(){
			if (btn_new.length === 0){
				// utility.animate_scroll_to_poisition(btn_scrollTop, 100);
				// utility.animate_scroll_to_element(jq_btn, 1000);
				utility.animate_scroll_to_poisition(bottom_dist, 1000);
			}else{
				// utility.animate_scroll_to_poisition(btn_scrollTop, 100);
				// utility.animate_scroll_to_element(btn_new, 1000);
				utility.animate_scroll_to_poisition(bottom_dist, 1000);
			}

			// 获取新加载的数据
			let request_obj = utility.autoSubRange(request.data_binding_xpath, request.data_binding_max);

			request.data_binding_sub_list = request_obj.list_sub_range_xpath;
			get_simple_list_table_data(request);
		}, turn_page_rate);
	}else if(request.todo === "refresh_preview"){
		if (request.todo_type === "data_binding_background"){
			c_data_binding_global.refresh_preview("data_binding", "background", request.color);
		}else if(request.todo_type === "data_binding_border"){
			c_data_binding_global.refresh_preview("data_binding", "border", request.color);
		}else if(request.todo_type === "max_background"){
			c_data_binding_global.refresh_preview("max", "background", request.color);
		}else if(request.todo_type === "max_border"){
			c_data_binding_global.refresh_preview("max", "border", request.color);
		}else if(request.todo_type === "sub_background"){
			c_data_binding_global.refresh_preview("sub", "background", request.color);
		}else if(request.todo_type === "sub_border"){
			c_data_binding_global.refresh_preview("sub", "border", request.color);
		}
	}else if(request.todo === "update_preview_info"){
		if (request.todo_type === "data_binding_background"){
			if (request.status === "activate"){
				c_data_binding_global.main_node.preview_settings.is_preview_background_color = true;
				c_data_binding_global.main_node.active_main_preview();
			}else if(request.status === "deactivate"){
				// 清除预览效果
				c_data_binding_global.main_node.clear_preview();
				// 取消激活状态
				c_data_binding_global.main_node.deactive_background_preview();
				// 显示预览效果
				c_data_binding_global.main_node.active_main_preview();
			}
		}else if(request.todo_type === "data_binding_border"){
			if (request.status === "activate"){
				c_data_binding_global.main_node.preview_settings.is_preview_border = true;
				c_data_binding_global.main_node.active_main_preview();
			}else if(request.status === "deactivate"){
				c_data_binding_global.main_node.clear_preview();
				c_data_binding_global.main_node.deactivate_border_preview();
				c_data_binding_global.main_node.active_main_preview();
			}
		}else if (request.todo_type === "max_background"){
			if (request.status === "activate"){
				c_data_binding_global.max_node.preview_settings.is_preview_background_color = true;
				c_data_binding_global.max_node.active_max_preview();
			}else if(request.status === "deactivate"){
				c_data_binding_global.max_node.clear_preview();
				c_data_binding_global.max_node.deactive_background_preview();
				c_data_binding_global.max_node.active_max_preview();
			}
		}else if (request.todo_type === "max_border"){
			if (request.status === "activate"){
				c_data_binding_global.max_node.preview_settings.is_preview_border = true;
				c_data_binding_global.max_node.active_max_preview();
			}else if(request.status === "deactivate"){
				c_data_binding_global.max_node.clear_preview();
				c_data_binding_global.max_node.deactivate_border_preview();
				c_data_binding_global.max_node.active_max_preview();
			}
		}else if (request.todo_type === "sub_background"){
			if (request.status === "activate"){
				for (let i = 0; i < c_data_binding_global.sub_node_list.length; i++) {
					let node = c_data_binding_global.sub_node_list[i];
					node.preview_settings.is_preview_background_color = true;
					node.active_sub_preview();
				}
			}else if(request.status === "deactivate"){
				for (let i = 0; i < c_data_binding_global.sub_node_list.length; i++) {
					let node = c_data_binding_global.sub_node_list[i];
					node.clear_preview();
					node.deactive_background_preview();
					node.active_sub_preview();
				}
			}
		}else if (request.todo_type === "sub_border"){
			if (request.status === "activate"){
				for (let i = 0; i < c_data_binding_global.sub_node_list.length; i++) {
					let node = c_data_binding_global.sub_node_list[i];
					node.preview_settings.is_preview_border = true;
					node.active_sub_preview();
				}
			}else if(request.status === "deactivate"){
				for (let i = 0; i < c_data_binding_global.sub_node_list.length; i++) {
					let node = c_data_binding_global.sub_node_list[i];
					node.clear_preview();
					node.deactivate_border_preview();
					node.active_sub_preview();
				}
			}
		}
	}
});
